@studyportals/fawkes 8.7.0 → 8.7.1-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/organisations-seo/index.d.ts +3 -3
- package/dist/organisations-seo/index.js +1 -1
- package/dist/programmes-seo/index.d.ts +5 -5
- package/dist/programmes-seo/index.js +1 -1
- package/dist/scholarships-seo/index.d.ts +4 -4
- package/dist/scholarships-seo/index.js +2 -2
- package/dist/sitemap-generator-seo/index.d.ts +14 -14
- package/dist/sitemap-generator-seo/index.js +5 -5
- package/dist/src/common/IDependencies.d.ts +1 -1
- package/dist/src/common/IPresenter.d.ts +1 -1
- package/dist/src/common/ISearchDependencies.d.ts +1 -1
- package/dist/src/common/ISeoDependencies.d.ts +2 -2
- package/dist/src/common/ISitemapDependencies.d.ts +2 -2
- package/dist/src/common/ISitemapUrlGenerator.d.ts +1 -1
- package/dist/src/common/policies/BaseSeoIndexabilityPolicy.d.ts +1 -1
- package/dist/src/common/policies/BaseSeoIndexabilityPolicy.js +2 -2
- package/dist/src/common/rules/NoFiltersSelectedRule.d.ts +2 -2
- package/dist/src/common/rules/OnlineAttendanceRule.d.ts +1 -1
- package/dist/src/common/rules/OnlineAttendanceRule.js +1 -1
- package/dist/src/common/rules/OnlyFiltersSelectedRule.d.ts +2 -2
- package/dist/src/common/rules/SingleValueSelectedForFilterRule.d.ts +2 -2
- package/dist/src/organisations/IOrganisationSearchApplicationState.d.ts +1 -1
- package/dist/src/organisations/ISeoSortingState.d.ts +1 -1
- package/dist/src/organisations/SearchIndexabilityManager.d.ts +4 -4
- package/dist/src/organisations/SearchIndexabilityManager.js +2 -2
- package/dist/src/organisations/policies/OrganisationsSeoIndexabilityPolicy.d.ts +3 -3
- package/dist/src/organisations/policies/OrganisationsSeoIndexabilityPolicy.js +3 -3
- package/dist/src/organisations/policies/RankedOrganisationsSeoIndexabilityPolicy.d.ts +1 -1
- package/dist/src/organisations/policies/RankedOrganisationsSeoIndexabilityPolicy.js +1 -1
- package/dist/src/organisations/policies/our-picks/Area.d.ts +5 -5
- package/dist/src/organisations/policies/our-picks/Area.js +6 -6
- package/dist/src/organisations/policies/our-picks/AreaAttendance.d.ts +7 -7
- package/dist/src/organisations/policies/our-picks/AreaAttendance.js +9 -9
- package/dist/src/organisations/policies/our-picks/Attendance.d.ts +6 -6
- package/dist/src/organisations/policies/our-picks/Attendance.js +7 -7
- package/dist/src/organisations/policies/our-picks/Continent.d.ts +5 -5
- package/dist/src/organisations/policies/our-picks/Continent.js +6 -6
- package/dist/src/organisations/policies/our-picks/Country.d.ts +5 -5
- package/dist/src/organisations/policies/our-picks/Country.js +6 -6
- package/dist/src/organisations/policies/our-picks/CountryAreaCity.d.ts +6 -6
- package/dist/src/organisations/policies/our-picks/CountryAreaCity.js +7 -7
- package/dist/src/organisations/policies/our-picks/CountryAttendance.d.ts +7 -7
- package/dist/src/organisations/policies/our-picks/CountryAttendance.js +9 -9
- package/dist/src/organisations/policies/our-picks/CountryCity.d.ts +6 -6
- package/dist/src/organisations/policies/our-picks/CountryCity.js +7 -7
- package/dist/src/organisations/policies/our-picks/Unfiltered.d.ts +4 -4
- package/dist/src/organisations/policies/our-picks/Unfiltered.js +4 -4
- package/dist/src/organisations/policies/ranked/RankedArea.d.ts +4 -4
- package/dist/src/organisations/policies/ranked/RankedArea.js +4 -4
- package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.d.ts +5 -5
- package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.js +6 -6
- package/dist/src/organisations/policies/ranked/RankedAttendance.d.ts +5 -5
- package/dist/src/organisations/policies/ranked/RankedAttendance.js +5 -5
- package/dist/src/organisations/policies/ranked/RankedAttendanceDiscipline.d.ts +5 -5
- package/dist/src/organisations/policies/ranked/RankedAttendanceDiscipline.js +6 -6
- package/dist/src/organisations/policies/ranked/RankedContinent.d.ts +4 -4
- package/dist/src/organisations/policies/ranked/RankedContinent.js +4 -4
- package/dist/src/organisations/policies/ranked/RankedContinentAttendance.d.ts +6 -6
- package/dist/src/organisations/policies/ranked/RankedContinentAttendance.js +7 -7
- package/dist/src/organisations/policies/ranked/RankedCountry.d.ts +4 -4
- package/dist/src/organisations/policies/ranked/RankedCountry.js +4 -4
- package/dist/src/organisations/policies/ranked/RankedCountryAttendance.d.ts +5 -5
- package/dist/src/organisations/policies/ranked/RankedCountryAttendance.js +6 -6
- package/dist/src/organisations/policies/ranked/RankedCountryDiscipline.d.ts +4 -4
- package/dist/src/organisations/policies/ranked/RankedCountryDiscipline.js +5 -5
- package/dist/src/organisations/policies/ranked/RankedDiscipline.d.ts +4 -4
- package/dist/src/organisations/policies/ranked/RankedDiscipline.js +4 -4
- package/dist/src/organisations/policies/ranked/RankedUnfiltered.d.ts +3 -3
- package/dist/src/organisations/policies/ranked/RankedUnfiltered.js +2 -2
- package/dist/src/organisations/rules/BaseSearchVolumeOrganisationsRule.d.ts +3 -3
- package/dist/src/organisations/rules/ContinentIsEuropeRule.d.ts +1 -1
- package/dist/src/organisations/rules/ContinentIsEuropeRule.js +1 -1
- package/dist/src/organisations/rules/ExcludeByIdForCitiesRule.d.ts +3 -3
- package/dist/src/organisations/rules/MinimumAmountOfRankedResultsRule.d.ts +3 -3
- package/dist/src/organisations/rules/MinimumAmountOfRankedResultsRule.js +1 -1
- package/dist/src/organisations/rules/MinimumAmountOfResultsRule.d.ts +4 -4
- package/dist/src/organisations/rules/MinimumAmountOfResultsRule.js +1 -1
- package/dist/src/organisations/rules/NoFiltersSelectedRule.d.ts +2 -2
- package/dist/src/organisations/types/IOrganisationSearchDependencies.d.ts +2 -2
- package/dist/src/organisations/types/IOrganisationsSitemapDependencies.d.ts +3 -3
- package/dist/src/presenters/AreaPresenter.d.ts +1 -1
- package/dist/src/presenters/AttendancePresenter.d.ts +1 -1
- package/dist/src/presenters/CityPresenter.d.ts +1 -1
- package/dist/src/presenters/ContinentPresenter.d.ts +1 -1
- package/dist/src/presenters/CountryPresenter.d.ts +1 -1
- package/dist/src/presenters/DegreePresenter.d.ts +1 -1
- package/dist/src/presenters/DisciplinePresenter.d.ts +1 -1
- package/dist/src/presenters/DurationPresenter.d.ts +1 -1
- package/dist/src/presenters/EducationalFormPresenter.d.ts +1 -1
- package/dist/src/presenters/FormatPresenter.d.ts +1 -1
- package/dist/src/presenters/SpecialProgrammesPresenter.d.ts +1 -1
- package/dist/src/presenters/TuitionFeePresenter.d.ts +1 -1
- package/dist/src/programmes/BaseProgrammeFilterKeyValueRule.d.ts +2 -2
- package/dist/src/programmes/BaseProgrammeFilterKeyValueRule.js +1 -1
- package/dist/src/programmes/BaseProgrammeRule.d.ts +2 -2
- package/dist/src/programmes/IProgrammeRule.d.ts +2 -2
- package/dist/src/programmes/ProgrammesBaseIndexabilityPolicy.d.ts +3 -3
- package/dist/src/programmes/ProgrammesBaseIndexabilityPolicy.js +1 -1
- package/dist/src/programmes/SearchIndexabilityManager.d.ts +4 -4
- package/dist/src/programmes/SearchIndexabilityManager.js +8 -4
- package/dist/src/programmes/policies/Area.d.ts +3 -3
- package/dist/src/programmes/policies/Area.js +4 -4
- package/dist/src/programmes/policies/Attendance.d.ts +4 -4
- package/dist/src/programmes/policies/Attendance.js +5 -5
- package/dist/src/programmes/policies/AttendanceArea.d.ts +4 -4
- package/dist/src/programmes/policies/AttendanceArea.js +6 -6
- package/dist/src/programmes/policies/AttendanceContinent.d.ts +4 -4
- package/dist/src/programmes/policies/AttendanceContinent.js +6 -6
- package/dist/src/programmes/policies/AttendanceDegree.d.ts +2 -2
- package/dist/src/programmes/policies/AttendanceDegree.js +5 -5
- package/dist/src/programmes/policies/AttendanceDuration.d.ts +5 -5
- package/dist/src/programmes/policies/AttendanceDuration.js +7 -7
- package/dist/src/programmes/policies/AttendanceFormat.d.ts +4 -4
- package/dist/src/programmes/policies/AttendanceFormat.js +6 -6
- package/dist/src/programmes/policies/Continent.d.ts +3 -3
- package/dist/src/programmes/policies/Continent.js +4 -4
- package/dist/src/programmes/policies/ContinentDuration.d.ts +3 -3
- package/dist/src/programmes/policies/ContinentDuration.js +5 -5
- package/dist/src/programmes/policies/ContinentFormat.d.ts +3 -3
- package/dist/src/programmes/policies/ContinentFormat.js +5 -5
- package/dist/src/programmes/policies/ContinentSpecialProgrammes.d.ts +4 -4
- package/dist/src/programmes/policies/ContinentSpecialProgrammes.js +6 -6
- package/dist/src/programmes/policies/Country.d.ts +3 -3
- package/dist/src/programmes/policies/Country.js +4 -4
- package/dist/src/programmes/policies/CountryAttendance.d.ts +4 -4
- package/dist/src/programmes/policies/CountryAttendance.js +6 -6
- package/dist/src/programmes/policies/CountryAttendanceDegree.d.ts +4 -4
- package/dist/src/programmes/policies/CountryAttendanceDegree.js +7 -7
- package/dist/src/programmes/policies/CountryDegree.d.ts +2 -2
- package/dist/src/programmes/policies/CountryDegree.js +5 -5
- package/dist/src/programmes/policies/CountryDuration.d.ts +3 -3
- package/dist/src/programmes/policies/CountryDuration.js +5 -5
- package/dist/src/programmes/policies/CountryDurationDegree.d.ts +3 -3
- package/dist/src/programmes/policies/CountryDurationDegree.js +6 -6
- package/dist/src/programmes/policies/CountryEducationalForm.d.ts +2 -2
- package/dist/src/programmes/policies/CountryEducationalForm.js +5 -5
- package/dist/src/programmes/policies/CountryFormat.d.ts +3 -3
- package/dist/src/programmes/policies/CountryFormat.js +5 -5
- package/dist/src/programmes/policies/CountrySpecialProgrammes.d.ts +4 -4
- package/dist/src/programmes/policies/CountrySpecialProgrammes.js +6 -6
- package/dist/src/programmes/policies/Degree.d.ts +3 -3
- package/dist/src/programmes/policies/Degree.js +4 -4
- package/dist/src/programmes/policies/DegreeArea.d.ts +3 -3
- package/dist/src/programmes/policies/DegreeArea.js +5 -5
- package/dist/src/programmes/policies/DegreeAttendanceDiscipline.d.ts +4 -4
- package/dist/src/programmes/policies/DegreeAttendanceDiscipline.js +7 -7
- package/dist/src/programmes/policies/DegreeAttendanceFormat.d.ts +4 -4
- package/dist/src/programmes/policies/DegreeAttendanceFormat.js +7 -7
- package/dist/src/programmes/policies/DegreeAttendanceSpecialProgrammes.d.ts +4 -4
- package/dist/src/programmes/policies/DegreeAttendanceSpecialProgrammes.js +7 -7
- package/dist/src/programmes/policies/DegreeContinent.d.ts +2 -2
- package/dist/src/programmes/policies/DegreeContinent.js +5 -5
- package/dist/src/programmes/policies/DegreeCountryAttendance.d.ts +3 -3
- package/dist/src/programmes/policies/DegreeCountryAttendance.js +6 -6
- package/dist/src/programmes/policies/DegreeCountryDiscipline.d.ts +3 -3
- package/dist/src/programmes/policies/DegreeCountryDiscipline.js +6 -6
- package/dist/src/programmes/policies/DegreeCountryTuitionFee.d.ts +3 -3
- package/dist/src/programmes/policies/DegreeCountryTuitionFee.js +6 -6
- package/dist/src/programmes/policies/DegreeDuration.d.ts +2 -2
- package/dist/src/programmes/policies/DegreeDuration.js +5 -5
- package/dist/src/programmes/policies/DegreeFormat.d.ts +2 -2
- package/dist/src/programmes/policies/DegreeFormat.js +5 -5
- package/dist/src/programmes/policies/DegreeSpecialProgrammes.d.ts +3 -3
- package/dist/src/programmes/policies/DegreeSpecialProgrammes.js +5 -5
- package/dist/src/programmes/policies/DegreeTuitionFee.d.ts +3 -3
- package/dist/src/programmes/policies/DegreeTuitionFee.js +5 -5
- package/dist/src/programmes/policies/{DisciplineTuitionFee.d.ts → DegreeTuitionFeeArea.d.ts} +5 -5
- package/dist/src/programmes/policies/{DegreeAreaTuitionFee.js → DegreeTuitionFeeArea.js} +7 -7
- package/dist/src/programmes/policies/{DegreeAttendanceTuitionFee.d.ts → DegreeTuitionFeeAttendance.d.ts} +2 -2
- package/dist/src/programmes/policies/{DegreeAttendanceTuitionFee.js → DegreeTuitionFeeAttendance.js} +7 -7
- package/dist/src/programmes/policies/{DegreeContinentTuitionFee.d.ts → DegreeTuitionFeeContinent.d.ts} +2 -2
- package/dist/src/programmes/policies/{DegreeContinentTuitionFee.js → DegreeTuitionFeeContinent.js} +6 -6
- package/dist/src/programmes/policies/{DegreeFormatTuitionFee.d.ts → DegreeTuitionFeeFormat.d.ts} +3 -3
- package/dist/src/programmes/policies/{DegreeFormatTuitionFee.js → DegreeTuitionFeeFormat.js} +9 -9
- package/dist/src/programmes/policies/Discipline.d.ts +3 -3
- package/dist/src/programmes/policies/Discipline.js +4 -4
- package/dist/src/programmes/policies/DisciplineAttendance.d.ts +4 -4
- package/dist/src/programmes/policies/DisciplineAttendance.js +6 -6
- package/dist/src/programmes/policies/DisciplineContinent.d.ts +3 -3
- package/dist/src/programmes/policies/DisciplineContinent.js +5 -5
- package/dist/src/programmes/policies/DisciplineContinentAttendance.d.ts +4 -4
- package/dist/src/programmes/policies/DisciplineContinentAttendance.js +7 -7
- package/dist/src/programmes/policies/DisciplineCountry.d.ts +3 -3
- package/dist/src/programmes/policies/DisciplineCountry.js +5 -5
- package/dist/src/programmes/policies/DisciplineCountryAttendance.d.ts +4 -4
- package/dist/src/programmes/policies/DisciplineCountryAttendance.js +7 -7
- package/dist/src/programmes/policies/DisciplineCountryEducationalForm.d.ts +2 -2
- package/dist/src/programmes/policies/DisciplineCountryEducationalForm.js +6 -6
- package/dist/src/programmes/policies/DisciplineCountryFormat.d.ts +3 -3
- package/dist/src/programmes/policies/DisciplineCountryFormat.js +6 -6
- package/dist/src/programmes/policies/DisciplineDegree.d.ts +3 -3
- package/dist/src/programmes/policies/DisciplineDegree.js +5 -5
- package/dist/src/programmes/policies/DisciplineDuration.d.ts +3 -3
- package/dist/src/programmes/policies/DisciplineDuration.js +5 -5
- package/dist/src/programmes/policies/DisciplineEducationalForm.d.ts +2 -2
- package/dist/src/programmes/policies/DisciplineEducationalForm.js +5 -5
- package/dist/src/programmes/policies/DisciplineFormat.d.ts +3 -3
- package/dist/src/programmes/policies/DisciplineFormat.js +5 -5
- package/dist/src/programmes/policies/DisciplineSpecialProgrammes.d.ts +3 -3
- package/dist/src/programmes/policies/DisciplineSpecialProgrammes.js +5 -5
- package/dist/src/programmes/policies/Duration.d.ts +3 -3
- package/dist/src/programmes/policies/Duration.js +4 -4
- package/dist/src/programmes/policies/Format.d.ts +3 -3
- package/dist/src/programmes/policies/Format.js +4 -4
- package/dist/src/programmes/policies/SpecialProgrammes.d.ts +3 -3
- package/dist/src/programmes/policies/SpecialProgrammes.js +4 -4
- package/dist/src/programmes/policies/TuitionFee.d.ts +3 -3
- package/dist/src/programmes/policies/TuitionFee.js +4 -4
- package/dist/src/programmes/policies/TuitionFeeAttendance.d.ts +4 -4
- package/dist/src/programmes/policies/TuitionFeeAttendance.js +6 -6
- package/dist/src/programmes/policies/TuitionFeeAttendanceDiscipline.d.ts +4 -4
- package/dist/src/programmes/policies/TuitionFeeAttendanceDiscipline.js +7 -7
- package/dist/src/programmes/policies/TuitionFeeContinent.d.ts +3 -3
- package/dist/src/programmes/policies/TuitionFeeContinent.js +5 -5
- package/dist/src/programmes/policies/TuitionFeeCountry.d.ts +3 -3
- package/dist/src/programmes/policies/TuitionFeeCountry.js +5 -5
- package/dist/src/programmes/policies/TuitionFeeDiscipline.d.ts +3 -3
- package/dist/src/programmes/policies/TuitionFeeDiscipline.js +5 -5
- package/dist/src/programmes/policies/Unfiltered.d.ts +2 -2
- package/dist/src/programmes/policies/Unfiltered.js +2 -2
- package/dist/src/programmes/policies/index.d.ts +4 -5
- package/dist/src/programmes/policies/index.js +4 -5
- package/dist/src/programmes/rules/DegreeAttendanceDisciplineRule.d.ts +2 -2
- package/dist/src/programmes/rules/DegreeAttendanceDisciplineSpecificRule.d.ts +2 -2
- package/dist/src/programmes/rules/DegreeCountryAttendanceSpecificRule.d.ts +2 -2
- package/dist/src/programmes/rules/DegreeCountryDisciplineSpecificRule.d.ts +2 -2
- package/dist/src/programmes/rules/DegreeCountryTuitionFeeSpecificRule.d.ts +2 -2
- package/dist/src/programmes/rules/DegreeDisciplineRule.d.ts +2 -2
- package/dist/src/programmes/rules/IndexableDegreeRule.d.ts +2 -2
- package/dist/src/programmes/rules/IndexableDegreeRule.js +1 -1
- package/dist/src/programmes/rules/IndexableDurationRule.d.ts +2 -2
- package/dist/src/programmes/rules/IndexableDurationRule.js +1 -1
- package/dist/src/programmes/rules/IndexableEducationalFormRule.d.ts +2 -2
- package/dist/src/programmes/rules/IndexableEducationalFormRule.js +1 -1
- package/dist/src/programmes/rules/IndexablePageNumberRule.js +1 -1
- package/dist/src/programmes/rules/MbaOrMscDegreeRule.d.ts +2 -2
- package/dist/src/programmes/rules/MinimumAmountOfResultsRule.d.ts +3 -3
- package/dist/src/programmes/rules/MinimumAmountOfResultsRule.js +1 -1
- package/dist/src/programmes/rules/NotDistanceLearningPortalRule.js +1 -1
- package/dist/src/programmes/rules/OneYearOnlyRule.d.ts +2 -2
- package/dist/src/programmes/types/IProgrammeSearchApplicationState.d.ts +1 -1
- package/dist/src/programmes/types/IProgrammeSearchDependencies.d.ts +1 -1
- package/dist/src/programmes/types/IProgrammeSearchSitemapDependencies.d.ts +1 -1
- package/dist/src/programmes/types/IProgrammeSitemapDependencies.d.ts +2 -2
- package/dist/src/programmes/types/IProgrammeSitemapUrlGenerator.d.ts +1 -1
- package/dist/src/scholarships/SearchIndexabilityManager.d.ts +5 -5
- package/dist/src/scholarships/SearchIndexabilityManager.js +1 -1
- package/dist/src/scholarships/policies/Area.d.ts +3 -3
- package/dist/src/scholarships/policies/Area.js +4 -4
- package/dist/src/scholarships/policies/Country.d.ts +3 -3
- package/dist/src/scholarships/policies/Country.js +4 -4
- package/dist/src/scholarships/policies/Discipline.d.ts +4 -4
- package/dist/src/scholarships/policies/Discipline.js +5 -5
- package/dist/src/scholarships/policies/DisciplineCountry.d.ts +3 -3
- package/dist/src/scholarships/policies/DisciplineCountry.js +5 -5
- package/dist/src/scholarships/policies/ScholarshipSeoIndexabilityPolicy.d.ts +2 -2
- package/dist/src/scholarships/policies/ScholarshipSeoIndexabilityPolicy.js +2 -2
- package/dist/src/scholarships/policies/Unfiltered.d.ts +2 -2
- package/dist/src/scholarships/policies/Unfiltered.js +2 -2
- package/dist/src/scholarships/policies/UniversityCountry.d.ts +3 -3
- package/dist/src/scholarships/policies/UniversityCountry.js +4 -4
- package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.d.ts +3 -3
- package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.js +1 -1
- package/dist/src/scholarships/rules/SearchVolumeAreasRule.d.ts +3 -3
- package/dist/src/scholarships/rules/SearchVolumeCountriesDisciplinesRule.d.ts +3 -3
- package/dist/src/scholarships/rules/SearchVolumeCountriesRule.d.ts +3 -3
- package/dist/src/scholarships/rules/SearchVolumeDisciplinesRule.d.ts +3 -3
- package/dist/src/scholarships/types/IScholarshipSeoDependencies.d.ts +1 -1
- package/dist/src/scholarships/types/IScholarshipSitemapDependencies.d.ts +2 -2
- package/dist/src/sitemap-generator/BaseSitemapUrlGeneratorManager.d.ts +3 -3
- package/dist/src/sitemap-generator/IRankingApiClient.d.ts +1 -1
- package/dist/src/sitemap-generator/ISearchApiClient.d.ts +1 -1
- package/dist/src/sitemap-generator/ISitemapUrlGeneratorManager.d.ts +3 -3
- package/dist/src/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.d.ts +4 -4
- package/dist/src/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.js +8 -8
- package/dist/src/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.d.ts +3 -3
- package/dist/src/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.js +15 -15
- package/dist/src/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.d.ts +3 -3
- package/dist/src/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.js +7 -7
- package/dist/src/structured-data/OrganisationStructuredDataFactory.d.ts +1 -1
- package/dist/src/structured-data/ProgrammeStructuredDataFactory.d.ts +1 -1
- package/dist/tests/common/rules/NoFiltersSelectedRule.test.d.mts +1 -0
- package/dist/tests/common/rules/NoFiltersSelectedRule.test.mjs +40 -0
- package/dist/tests/common/rules/OnlyFiltersSelectedRule.test.d.mts +1 -0
- package/dist/tests/common/rules/OnlyFiltersSelectedRule.test.mjs +70 -0
- package/dist/tests/common/rules/SingleValueSelectedForFilterRule.test.d.mts +1 -0
- package/dist/tests/common/rules/SingleValueSelectedForFilterRule.test.mjs +54 -0
- package/dist/tests/organisations/policies/our-picks/Area.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/Area.test.mjs +125 -0
- package/dist/tests/organisations/policies/our-picks/AreaAttendance.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/AreaAttendance.test.mjs +238 -0
- package/dist/tests/organisations/policies/our-picks/Attendance.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/Attendance.test.mjs +119 -0
- package/dist/tests/organisations/policies/our-picks/Continent.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/Continent.test.mjs +105 -0
- package/dist/tests/organisations/policies/our-picks/Country.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/Country.test.mjs +109 -0
- package/dist/tests/organisations/policies/our-picks/CountryAreaCity.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/CountryAreaCity.test.mjs +152 -0
- package/dist/tests/organisations/policies/our-picks/CountryAttendance.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/CountryAttendance.test.mjs +223 -0
- package/dist/tests/organisations/policies/our-picks/CountryCity.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/CountryCity.test.mjs +109 -0
- package/dist/tests/organisations/policies/our-picks/Unfiltered.test.d.mts +1 -0
- package/dist/tests/organisations/policies/our-picks/Unfiltered.test.mjs +60 -0
- package/dist/tests/organisations/policies/ranked/RankedArea.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedArea.test.mjs +149 -0
- package/dist/tests/organisations/policies/ranked/RankedAreaDiscipline.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedAreaDiscipline.test.mjs +237 -0
- package/dist/tests/organisations/policies/ranked/RankedAttendance.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedAttendance.test.mjs +139 -0
- package/dist/tests/organisations/policies/ranked/RankedAttendanceDiscipline.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedAttendanceDiscipline.test.mjs +224 -0
- package/dist/tests/organisations/policies/ranked/RankedContinent.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedContinent.test.mjs +125 -0
- package/dist/tests/organisations/policies/ranked/RankedContinentAttendance.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedContinentAttendance.test.mjs +253 -0
- package/dist/tests/organisations/policies/ranked/RankedCountry.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedCountry.test.mjs +131 -0
- package/dist/tests/organisations/policies/ranked/RankedCountryAttendance.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedCountryAttendance.test.mjs +230 -0
- package/dist/tests/organisations/policies/ranked/RankedCountryDiscipline.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedCountryDiscipline.test.mjs +197 -0
- package/dist/tests/organisations/policies/ranked/RankedDiscipline.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedDiscipline.test.mjs +124 -0
- package/dist/tests/organisations/policies/ranked/RankedUnfiltered.test.d.mts +1 -0
- package/dist/tests/organisations/policies/ranked/RankedUnfiltered.test.mjs +75 -0
- package/dist/tests/organisations/rules/ContinentIsEuropeRule.test.d.mts +1 -0
- package/dist/tests/organisations/rules/ContinentIsEuropeRule.test.mjs +59 -0
- package/dist/tests/organisations/rules/MinimumAmountOfRankedResultsRule.test.d.mts +1 -0
- package/dist/tests/organisations/rules/MinimumAmountOfRankedResultsRule.test.mjs +77 -0
- package/dist/tests/organisations/rules/MinimumAmountOfResultsRule.test.d.mts +1 -0
- package/dist/tests/organisations/rules/MinimumAmountOfResultsRule.test.mjs +77 -0
- package/dist/tests/organisations/rules/OnlineAttendanceRule.test.d.mts +1 -0
- package/dist/tests/organisations/rules/OnlineAttendanceRule.test.mjs +59 -0
- package/dist/tests/organisations/rules/SearchVolumeAreasAttendanceRule.test.d.mts +1 -0
- package/dist/tests/organisations/rules/SearchVolumeAreasAttendanceRule.test.mjs +59 -0
- package/dist/tests/organisations/rules/SearchVolumeAreasDisciplineRule.test.d.mts +1 -0
- package/dist/tests/organisations/rules/SearchVolumeAreasDisciplineRule.test.mjs +59 -0
- package/dist/tests/organisations/rules/SearchVolumeCountriesAttendanceRule.test.d.mts +1 -0
- package/dist/tests/organisations/rules/SearchVolumeCountriesAttendanceRule.test.mjs +59 -0
- package/dist/tests/organisations/utils/SearchDependencies.util.d.mts +20 -0
- package/dist/tests/organisations/utils/SearchDependencies.util.mjs +88 -0
- package/dist/tests/organisations/utils/SitemapDependencies.util.d.mts +18 -0
- package/dist/tests/organisations/utils/SitemapDependencies.util.mjs +54 -0
- package/dist/tests/presenters/AreaPresenter.test.d.mts +1 -0
- package/dist/tests/presenters/AreaPresenter.test.mjs +46 -0
- package/dist/tests/presenters/AttendancePresenter.test.d.mts +1 -0
- package/dist/tests/presenters/AttendancePresenter.test.mjs +41 -0
- package/dist/tests/presenters/ContinentPresenter.test.d.mts +1 -0
- package/dist/tests/presenters/ContinentPresenter.test.mjs +44 -0
- package/dist/tests/presenters/CountryPresenter.test.d.mts +1 -0
- package/dist/tests/presenters/CountryPresenter.test.mjs +50 -0
- package/dist/tests/presenters/DegreePresenter.test.d.mts +1 -0
- package/dist/tests/presenters/DegreePresenter.test.mjs +51 -0
- package/dist/tests/presenters/DisciplinePresenter.test.d.mts +1 -0
- package/dist/tests/presenters/DisciplinePresenter.test.mjs +40 -0
- package/dist/tests/presenters/DurationPresenter.test.d.mts +1 -0
- package/dist/tests/presenters/DurationPresenter.test.mjs +64 -0
- package/dist/tests/presenters/EducationalFormPresenter.test.d.mts +1 -0
- package/dist/tests/presenters/EducationalFormPresenter.test.mjs +60 -0
- package/dist/tests/presenters/FormatPresenter.test.d.mts +1 -0
- package/dist/tests/presenters/FormatPresenter.test.mjs +43 -0
- package/dist/tests/presenters/SpecialProgrammesPresenter.test.d.mts +1 -0
- package/dist/tests/presenters/SpecialProgrammesPresenter.test.mjs +66 -0
- package/dist/tests/presenters/TuitionFeePresenter.test.d.mts +1 -0
- package/dist/tests/presenters/TuitionFeePresenter.test.mjs +52 -0
- package/dist/tests/programmes/policies/Area.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Area.test.mjs +153 -0
- package/dist/tests/programmes/policies/Attendance.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Attendance.test.mjs +173 -0
- package/dist/tests/programmes/policies/AttendanceDegree.test.d.mts +1 -0
- package/dist/tests/programmes/policies/AttendanceDegree.test.mjs +291 -0
- package/dist/tests/programmes/policies/Continent.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Continent.test.mjs +169 -0
- package/dist/tests/programmes/policies/Country.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Country.test.mjs +164 -0
- package/dist/tests/programmes/policies/CountryAttendance.test.d.mts +1 -0
- package/dist/tests/programmes/policies/CountryAttendance.test.mjs +251 -0
- package/dist/tests/programmes/policies/CountryAttendanceDegree.test.d.mts +1 -0
- package/dist/tests/programmes/policies/CountryAttendanceDegree.test.mjs +337 -0
- package/dist/tests/programmes/policies/CountryDegree.test.d.mts +1 -0
- package/dist/tests/programmes/policies/CountryDegree.test.mjs +262 -0
- package/dist/tests/programmes/policies/CountryDuration.test.d.mts +1 -0
- package/dist/tests/programmes/policies/CountryDuration.test.mjs +234 -0
- package/dist/tests/programmes/policies/CountryDurationDegree.test.d.mts +1 -0
- package/dist/tests/programmes/policies/CountryDurationDegree.test.mjs +304 -0
- package/dist/tests/programmes/policies/CountryEducationalForm.test.d.mts +1 -0
- package/dist/tests/programmes/policies/CountryEducationalForm.test.mjs +260 -0
- package/dist/tests/programmes/policies/CountryFormat.test.d.mts +1 -0
- package/dist/tests/programmes/policies/CountryFormat.test.mjs +253 -0
- package/dist/tests/programmes/policies/DegreeAttendanceDiscipline.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DegreeAttendanceDiscipline.test.mjs +179 -0
- package/dist/tests/programmes/policies/DegreeCountryAttendance.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DegreeCountryAttendance.test.mjs +267 -0
- package/dist/tests/programmes/policies/DegreeCountryTuitionFee.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DegreeCountryTuitionFee.test.mjs +217 -0
- package/dist/tests/programmes/policies/DegreeFormat.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DegreeFormat.test.mjs +221 -0
- package/dist/tests/programmes/policies/Discipline.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Discipline.test.mjs +159 -0
- package/dist/tests/programmes/policies/DisciplineAttendance.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineAttendance.test.mjs +292 -0
- package/dist/tests/programmes/policies/DisciplineContinent.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineContinent.test.mjs +253 -0
- package/dist/tests/programmes/policies/DisciplineCountry.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineCountry.test.mjs +244 -0
- package/dist/tests/programmes/policies/DisciplineCountryEducationalForm.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineCountryEducationalForm.test.mjs +345 -0
- package/dist/tests/programmes/policies/DisciplineDegree.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineDegree.test.mjs +273 -0
- package/dist/tests/programmes/policies/DisciplineDuration.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineDuration.test.mjs +278 -0
- package/dist/tests/programmes/policies/DisciplineEducationalForm.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineEducationalForm.test.mjs +302 -0
- package/dist/tests/programmes/policies/DisciplineFormat.test.d.mts +1 -0
- package/dist/tests/programmes/policies/DisciplineFormat.test.mjs +266 -0
- package/dist/tests/programmes/policies/Duration.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Duration.test.mjs +179 -0
- package/dist/tests/programmes/policies/Format.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Format.test.mjs +117 -0
- package/dist/tests/programmes/policies/NewRulesValidation.test.d.mts +1 -0
- package/dist/tests/programmes/policies/NewRulesValidation.test.mjs +320 -0
- package/dist/tests/programmes/policies/SpecialProgrammes.test.d.mts +1 -0
- package/dist/tests/programmes/policies/SpecialProgrammes.test.mjs +171 -0
- package/dist/tests/programmes/policies/TuitionFeeAttendanceDiscipline.test.d.mts +1 -0
- package/dist/tests/programmes/policies/TuitionFeeAttendanceDiscipline.test.mjs +360 -0
- package/dist/tests/programmes/policies/TuitionFeeContinent.test.d.mts +1 -0
- package/dist/tests/programmes/policies/TuitionFeeContinent.test.mjs +293 -0
- package/dist/tests/programmes/policies/TuitionFeeCountry.test.d.mts +1 -0
- package/dist/tests/programmes/policies/TuitionFeeCountry.test.mjs +266 -0
- package/dist/tests/programmes/policies/TuitionFeeDiscipline.test.d.mts +1 -0
- package/dist/tests/programmes/policies/TuitionFeeDiscipline.test.mjs +267 -0
- package/dist/tests/programmes/policies/Unfiltered.test.d.mts +1 -0
- package/dist/tests/programmes/policies/Unfiltered.test.mjs +90 -0
- package/dist/tests/programmes/rules/AffordableTuitionFeeRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/AffordableTuitionFeeRule.test.mjs +27 -0
- package/dist/tests/programmes/rules/DegreeCountrySpecificRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/DegreeCountrySpecificRule.test.mjs +121 -0
- package/dist/tests/programmes/rules/DegreeDisciplineRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/DegreeDisciplineRule.test.mjs +169 -0
- package/dist/tests/programmes/rules/IndexableDegreeRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/IndexableDegreeRule.test.mjs +101 -0
- package/dist/tests/programmes/rules/IndexableDurationRule.test..d.mts +1 -0
- package/dist/tests/programmes/rules/IndexableDurationRule.test..mjs +25 -0
- package/dist/tests/programmes/rules/IndexableEducationalFormRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/IndexableEducationalFormRule.test.mjs +27 -0
- package/dist/tests/programmes/rules/IndexablePageNumberRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/IndexablePageNumberRule.test.mjs +51 -0
- package/dist/tests/programmes/rules/MbaDegreeRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/MbaDegreeRule.test.mjs +55 -0
- package/dist/tests/programmes/rules/MbaOrMscDegreeRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/MbaOrMscDegreeRule.test.mjs +53 -0
- package/dist/tests/programmes/rules/MinimumAmountOfResultsRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/MinimumAmountOfResultsRule.test.mjs +79 -0
- package/dist/tests/programmes/rules/NotDistanceLearningPortalRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/NotDistanceLearningPortalRule.test.mjs +57 -0
- package/dist/tests/programmes/rules/OneYearDurationRule.test..d.mts +1 -0
- package/dist/tests/programmes/rules/OneYearDurationRule.test..mjs +40 -0
- package/dist/tests/programmes/rules/OnlineAttendanceRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/OnlineAttendanceRule.test.mjs +69 -0
- package/dist/tests/programmes/rules/PartTimeFormatRule.test.d.mts +1 -0
- package/dist/tests/programmes/rules/PartTimeFormatRule.test.mjs +27 -0
- package/dist/tests/programmes/utils/SearchDependencies.util.d.mts +16 -0
- package/dist/tests/programmes/utils/SearchDependencies.util.mjs +73 -0
- package/dist/tests/programmes/utils/SitemapDependencies.util.d.mts +15 -0
- package/dist/tests/programmes/utils/SitemapDependencies.util.mjs +49 -0
- package/dist/tests/scholarships/policies/Area.test.d.mts +1 -0
- package/dist/tests/scholarships/policies/Area.test.mjs +121 -0
- package/dist/tests/scholarships/policies/Country.test.d.mts +1 -0
- package/dist/tests/scholarships/policies/Country.test.mjs +97 -0
- package/dist/tests/scholarships/policies/Discipline.test.d.mts +1 -0
- package/dist/tests/scholarships/policies/Discipline.test.mjs +93 -0
- package/dist/tests/scholarships/policies/DisciplineCountry.test.d.mts +1 -0
- package/dist/tests/scholarships/policies/DisciplineCountry.test.mjs +151 -0
- package/dist/tests/scholarships/policies/Unfiltered.test.d.mts +1 -0
- package/dist/tests/scholarships/policies/Unfiltered.test.mjs +44 -0
- package/dist/tests/scholarships/policies/UniversityCountry.test.d.mts +1 -0
- package/dist/tests/scholarships/policies/UniversityCountry.test.mjs +115 -0
- package/dist/tests/scholarships/rules/ExceptAustaliaAreasRule.test.d.mts +1 -0
- package/dist/tests/scholarships/rules/ExceptAustaliaAreasRule.test.mjs +64 -0
- package/dist/tests/scholarships/rules/SearchVolumeAreasRule.test.d.mts +1 -0
- package/dist/tests/scholarships/rules/SearchVolumeAreasRule.test.mjs +62 -0
- package/dist/tests/scholarships/rules/SearchVolumeCountriesDisciplinesRule.test.d.mts +1 -0
- package/dist/tests/scholarships/rules/SearchVolumeCountriesDisciplinesRule.test.mjs +114 -0
- package/dist/tests/scholarships/rules/SearchVolumeCountriesRule.test.d.mts +1 -0
- package/dist/tests/scholarships/rules/SearchVolumeCountriesRule.test.mjs +62 -0
- package/dist/tests/scholarships/rules/SearchVolumeDisciplinesRule.test.d.mts +1 -0
- package/dist/tests/scholarships/rules/SearchVolumeDisciplinesRule.test.mjs +62 -0
- package/dist/tests/scholarships/utils/SearchDependencies.util.d.mts +16 -0
- package/dist/tests/scholarships/utils/SearchDependencies.util.mjs +70 -0
- package/dist/tests/scholarships/utils/SitemapDependencies.util.d.mts +11 -0
- package/dist/tests/scholarships/utils/SitemapDependencies.util.mjs +33 -0
- package/dist/tests/sitemap-generator/BaseSitemapUrlGeneratorManager.test.d.mts +1 -0
- package/dist/tests/sitemap-generator/BaseSitemapUrlGeneratorManager.test.mjs +82 -0
- package/dist/tests/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.test.d.mts +1 -0
- package/dist/tests/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.test.mjs +85 -0
- package/dist/tests/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.test.d.mts +1 -0
- package/dist/tests/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.test.mjs +77 -0
- package/dist/tests/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.test.d.mts +1 -0
- package/dist/tests/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.test.mjs +60 -0
- package/dist/tests/structured-data/OrganisationStructuredDataFactory.test.d.mts +1 -0
- package/dist/tests/structured-data/OrganisationStructuredDataFactory.test.mjs +334 -0
- package/dist/tests/structured-data/ProgrammeStructuredDataFactory.test.d.mts +1 -0
- package/dist/tests/structured-data/ProgrammeStructuredDataFactory.test.mjs +562 -0
- package/dist/tests/structured-data/ScholarshipStructuredDataFactory.test.d.mts +1 -0
- package/dist/tests/structured-data/ScholarshipStructuredDataFactory.test.mjs +292 -0
- package/dist/tests/structured-data/SearchStructuredDataFactory.paywall.test.d.mts +1 -0
- package/dist/tests/structured-data/SearchStructuredDataFactory.paywall.test.mjs +258 -0
- package/package.json +1 -1
- package/dist/src/programmes/policies/AttendanceTuitionFee.d.ts +0 -17
- package/dist/src/programmes/policies/AttendanceTuitionFee.js +0 -51
- package/dist/src/programmes/policies/ContinentTuitionFee.d.ts +0 -16
- package/dist/src/programmes/policies/ContinentTuitionFee.js +0 -46
- package/dist/src/programmes/policies/CountryTuitionFee.d.ts +0 -16
- package/dist/src/programmes/policies/CountryTuitionFee.js +0 -46
- package/dist/src/programmes/policies/DegreeAreaTuitionFee.d.ts +0 -16
- package/dist/src/programmes/policies/DisciplineTuitionFee.js +0 -46
- package/dist/src/programmes/policies/DisciplineTuitionFeeAttendance.d.ts +0 -17
- package/dist/src/programmes/policies/DisciplineTuitionFeeAttendance.js +0 -54
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import Validator from '@adobe/structured-data-validator';
|
|
3
|
+
import { ProgrammeStructuredDataFactory } from '@/structured-data/ProgrammeStructuredDataFactory';
|
|
4
|
+
describe('ProgrammeStructuredDataFactory', () => {
|
|
5
|
+
let factory;
|
|
6
|
+
let mockCurrencyService;
|
|
7
|
+
let mockProgrammeCards;
|
|
8
|
+
let mockFaqItems;
|
|
9
|
+
let mockBreadcrumbs;
|
|
10
|
+
let validator;
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
// Fetch the current schema.org schema and create validator instance
|
|
13
|
+
const schemaOrgJson = await (await fetch('https://schema.org/version/latest/schemaorg-current-https.jsonld')).json();
|
|
14
|
+
validator = new Validator(schemaOrgJson);
|
|
15
|
+
// Mock the currency conversion service
|
|
16
|
+
mockCurrencyService = {
|
|
17
|
+
convert: vi.fn().mockResolvedValue(25000) // Mock conversion to USD
|
|
18
|
+
};
|
|
19
|
+
factory = new ProgrammeStructuredDataFactory(mockCurrencyService);
|
|
20
|
+
Object.defineProperty(global, 'window', {
|
|
21
|
+
value: {
|
|
22
|
+
location: {
|
|
23
|
+
host: 'studyportals.com'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
// Create mock data
|
|
28
|
+
setupMockData();
|
|
29
|
+
});
|
|
30
|
+
function setupMockData() {
|
|
31
|
+
// Mock FAQ items
|
|
32
|
+
mockFaqItems = [
|
|
33
|
+
{
|
|
34
|
+
question: 'What are the admission requirements?',
|
|
35
|
+
answer: '<p>You need a bachelor\'s degree with <ul><li>GPA 3.0+</li><li>English proficiency</li></ul></p>'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
question: 'How long is the program?',
|
|
39
|
+
answer: '<p>The program duration is 2 years full-time.</p>'
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
// Mock breadcrumbs
|
|
43
|
+
mockBreadcrumbs = [
|
|
44
|
+
{
|
|
45
|
+
name: 'Home',
|
|
46
|
+
position: 1,
|
|
47
|
+
url: 'https://localhost:8080/'
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'Study Abroad',
|
|
51
|
+
position: 2,
|
|
52
|
+
url: 'https://localhost:8080/study-abroad'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'Computer Science Programs',
|
|
56
|
+
position: 3,
|
|
57
|
+
url: 'https://localhost:8080/study-abroad/computer-science'
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
// Mock programme cards
|
|
61
|
+
mockProgrammeCards = createMockProgrammeCards();
|
|
62
|
+
}
|
|
63
|
+
function createMockProgrammeCards() {
|
|
64
|
+
const createMockTiming = (type, startDate) => ({
|
|
65
|
+
getType: vi.fn().mockReturnValue(type),
|
|
66
|
+
canShowStartDate: vi.fn().mockReturnValue(true),
|
|
67
|
+
getStartDate: vi.fn().mockReturnValue({
|
|
68
|
+
getDate: vi.fn().mockReturnValue(startDate)
|
|
69
|
+
}),
|
|
70
|
+
getDeadline: vi.fn().mockReturnValue(null),
|
|
71
|
+
canShowDeadline: vi.fn().mockReturnValue(false),
|
|
72
|
+
isApplyingAnytime: vi.fn().mockReturnValue(false),
|
|
73
|
+
isStartingAnytime: vi.fn().mockReturnValue(false)
|
|
74
|
+
});
|
|
75
|
+
const createMockTuitionFee = (target, amount, currency) => ({
|
|
76
|
+
getTarget: vi.fn().mockReturnValue(target),
|
|
77
|
+
getAmount: vi.fn().mockReturnValue(amount),
|
|
78
|
+
getCurrency: vi.fn().mockReturnValue(currency),
|
|
79
|
+
getOriginalAmount: vi.fn().mockReturnValue(amount),
|
|
80
|
+
getOriginalUnit: vi.fn().mockReturnValue(currency),
|
|
81
|
+
getUnit: vi.fn().mockReturnValue(currency),
|
|
82
|
+
isFree: vi.fn().mockReturnValue(false)
|
|
83
|
+
});
|
|
84
|
+
const createMockReviewRating = (avgRating, quantity) => ({
|
|
85
|
+
getAverageStarRating: vi.fn().mockReturnValue(avgRating),
|
|
86
|
+
getQuantity: vi.fn().mockReturnValue(quantity),
|
|
87
|
+
getAverage: vi.fn().mockReturnValue(avgRating),
|
|
88
|
+
hasEnoughQuantity: vi.fn().mockReturnValue(true)
|
|
89
|
+
});
|
|
90
|
+
const createMockLink = (url, description) => ({
|
|
91
|
+
getUrl: vi.fn().mockReturnValue(url),
|
|
92
|
+
getDescription: vi.fn().mockReturnValue(description),
|
|
93
|
+
canShowDescription: vi.fn().mockReturnValue(true)
|
|
94
|
+
});
|
|
95
|
+
// Card 1 - Full-time, on-campus program with ratings and tuition
|
|
96
|
+
const card1 = {
|
|
97
|
+
getTitle: vi.fn().mockReturnValue('Master of Computer Science'),
|
|
98
|
+
getSummary: vi.fn().mockReturnValue('Advanced computer science program focusing on AI and machine learning.'),
|
|
99
|
+
getProgrammeLink: vi.fn().mockReturnValue(createMockLink('/programmes/master-computer-science', 'Master of Computer Science')),
|
|
100
|
+
getUniversityLink: vi.fn().mockReturnValue(createMockLink('/universities/tech-university', 'Tech University')),
|
|
101
|
+
getReviewRating: vi.fn().mockReturnValue(createMockReviewRating(4.5, 120)),
|
|
102
|
+
getTuitionFees: vi.fn().mockReturnValue([
|
|
103
|
+
createMockTuitionFee('international', 30000, 'EUR'),
|
|
104
|
+
createMockTuitionFee('national', 15000, 'EUR')
|
|
105
|
+
]),
|
|
106
|
+
canShowTimings: vi.fn().mockReturnValue(true),
|
|
107
|
+
getTimings: vi.fn().mockReturnValue([
|
|
108
|
+
createMockTiming('international', new Date('2024-09-01')),
|
|
109
|
+
createMockTiming('national', new Date('2024-09-15'))
|
|
110
|
+
]),
|
|
111
|
+
isFullTime: vi.fn().mockReturnValue(true),
|
|
112
|
+
isPartTime: vi.fn().mockReturnValue(false),
|
|
113
|
+
isOnCampus: vi.fn().mockReturnValue(true),
|
|
114
|
+
isOnline: vi.fn().mockReturnValue(false),
|
|
115
|
+
isBlended: vi.fn().mockReturnValue(false),
|
|
116
|
+
// Add missing required properties with sensible defaults
|
|
117
|
+
getCountryIsoCode: vi.fn().mockReturnValue('US'),
|
|
118
|
+
getCover: vi.fn().mockReturnValue(null),
|
|
119
|
+
canShowCover: vi.fn().mockReturnValue(false),
|
|
120
|
+
getDegree: vi.fn().mockReturnValue(null),
|
|
121
|
+
getUniversity: vi.fn().mockReturnValue(null),
|
|
122
|
+
getCity: vi.fn().mockReturnValue(null),
|
|
123
|
+
getCountry: vi.fn().mockReturnValue(null),
|
|
124
|
+
getContinent: vi.fn().mockReturnValue(null),
|
|
125
|
+
getDiscipline: vi.fn().mockReturnValue(null),
|
|
126
|
+
getArea: vi.fn().mockReturnValue(null),
|
|
127
|
+
getSpecialProgrammes: vi.fn().mockReturnValue([]),
|
|
128
|
+
getEducationalForm: vi.fn().mockReturnValue(null),
|
|
129
|
+
getFormat: vi.fn().mockReturnValue(null),
|
|
130
|
+
getDuration: vi.fn().mockReturnValue(null),
|
|
131
|
+
getLanguage: vi.fn().mockReturnValue(null),
|
|
132
|
+
canShowTuitionFees: vi.fn().mockReturnValue(true),
|
|
133
|
+
getApplicationFees: vi.fn().mockReturnValue([]),
|
|
134
|
+
canShowApplicationFees: vi.fn().mockReturnValue(false),
|
|
135
|
+
getFees: vi.fn().mockReturnValue([]),
|
|
136
|
+
canShowFees: vi.fn().mockReturnValue(false),
|
|
137
|
+
getScholarships: vi.fn().mockReturnValue([]),
|
|
138
|
+
canShowScholarships: vi.fn().mockReturnValue(false),
|
|
139
|
+
canShowReviewRating: vi.fn().mockReturnValue(true),
|
|
140
|
+
getCredentials: vi.fn().mockReturnValue([]),
|
|
141
|
+
canShowCredentials: vi.fn().mockReturnValue(false),
|
|
142
|
+
getDeadlines: vi.fn().mockReturnValue([]),
|
|
143
|
+
canShowDeadlines: vi.fn().mockReturnValue(false),
|
|
144
|
+
getRequirements: vi.fn().mockReturnValue([]),
|
|
145
|
+
canShowRequirements: vi.fn().mockReturnValue(false),
|
|
146
|
+
getAttendance: vi.fn().mockReturnValue(null),
|
|
147
|
+
isDistance: vi.fn().mockReturnValue(false)
|
|
148
|
+
};
|
|
149
|
+
// Card 2 - Part-time, online program without ratings
|
|
150
|
+
const card2 = {
|
|
151
|
+
getTitle: vi.fn().mockReturnValue('MBA in Digital Marketing'),
|
|
152
|
+
getSummary: vi.fn().mockReturnValue('Flexible MBA program designed for working professionals.'),
|
|
153
|
+
getProgrammeLink: vi.fn().mockReturnValue(createMockLink('/programmes/mba-digital-marketing', 'MBA in Digital Marketing')),
|
|
154
|
+
getUniversityLink: vi.fn().mockReturnValue(createMockLink('/universities/business-school', 'International Business School')),
|
|
155
|
+
getReviewRating: vi.fn().mockReturnValue(undefined), // No review rating
|
|
156
|
+
getTuitionFees: vi.fn().mockReturnValue([
|
|
157
|
+
createMockTuitionFee('general', 45000, 'USD')
|
|
158
|
+
]),
|
|
159
|
+
canShowTimings: vi.fn().mockReturnValue(true),
|
|
160
|
+
getTimings: vi.fn().mockReturnValue([
|
|
161
|
+
createMockTiming('general', new Date('2024-10-01'))
|
|
162
|
+
]),
|
|
163
|
+
isFullTime: vi.fn().mockReturnValue(false),
|
|
164
|
+
isPartTime: vi.fn().mockReturnValue(true),
|
|
165
|
+
isOnCampus: vi.fn().mockReturnValue(false),
|
|
166
|
+
isOnline: vi.fn().mockReturnValue(true),
|
|
167
|
+
isBlended: vi.fn().mockReturnValue(false),
|
|
168
|
+
// Add missing required properties with sensible defaults
|
|
169
|
+
getCountryIsoCode: vi.fn().mockReturnValue('US'),
|
|
170
|
+
getCover: vi.fn().mockReturnValue(null),
|
|
171
|
+
canShowCover: vi.fn().mockReturnValue(false),
|
|
172
|
+
getDegree: vi.fn().mockReturnValue(null),
|
|
173
|
+
getUniversity: vi.fn().mockReturnValue(null),
|
|
174
|
+
getCity: vi.fn().mockReturnValue(null),
|
|
175
|
+
getCountry: vi.fn().mockReturnValue(null),
|
|
176
|
+
getContinent: vi.fn().mockReturnValue(null),
|
|
177
|
+
getDiscipline: vi.fn().mockReturnValue(null),
|
|
178
|
+
getArea: vi.fn().mockReturnValue(null),
|
|
179
|
+
getSpecialProgrammes: vi.fn().mockReturnValue([]),
|
|
180
|
+
getEducationalForm: vi.fn().mockReturnValue(null),
|
|
181
|
+
getFormat: vi.fn().mockReturnValue(null),
|
|
182
|
+
getDuration: vi.fn().mockReturnValue(null),
|
|
183
|
+
getLanguage: vi.fn().mockReturnValue(null),
|
|
184
|
+
canShowTuitionFees: vi.fn().mockReturnValue(true),
|
|
185
|
+
getApplicationFees: vi.fn().mockReturnValue([]),
|
|
186
|
+
canShowApplicationFees: vi.fn().mockReturnValue(false),
|
|
187
|
+
getFees: vi.fn().mockReturnValue([]),
|
|
188
|
+
canShowFees: vi.fn().mockReturnValue(false),
|
|
189
|
+
getScholarships: vi.fn().mockReturnValue([]),
|
|
190
|
+
canShowScholarships: vi.fn().mockReturnValue(false),
|
|
191
|
+
canShowReviewRating: vi.fn().mockReturnValue(false),
|
|
192
|
+
getCredentials: vi.fn().mockReturnValue([]),
|
|
193
|
+
canShowCredentials: vi.fn().mockReturnValue(false),
|
|
194
|
+
getDeadlines: vi.fn().mockReturnValue([]),
|
|
195
|
+
canShowDeadlines: vi.fn().mockReturnValue(false),
|
|
196
|
+
getRequirements: vi.fn().mockReturnValue([]),
|
|
197
|
+
canShowRequirements: vi.fn().mockReturnValue(false),
|
|
198
|
+
getAttendance: vi.fn().mockReturnValue(null),
|
|
199
|
+
isDistance: vi.fn().mockReturnValue(false)
|
|
200
|
+
};
|
|
201
|
+
// Card 3 - Blended program with ratings but no tuition fees
|
|
202
|
+
const card3 = {
|
|
203
|
+
getTitle: vi.fn().mockReturnValue('Bachelor of Engineering'),
|
|
204
|
+
getSummary: vi.fn().mockReturnValue('Comprehensive engineering program with flexible learning options.'),
|
|
205
|
+
getProgrammeLink: vi.fn().mockReturnValue(createMockLink('/programmes/bachelor-engineering', 'Bachelor of Engineering')),
|
|
206
|
+
getUniversityLink: vi.fn().mockReturnValue(createMockLink('/universities/engineering-institute', 'Engineering Institute')),
|
|
207
|
+
getReviewRating: vi.fn().mockReturnValue(createMockReviewRating(3.2, 85)),
|
|
208
|
+
getTuitionFees: vi.fn().mockReturnValue([
|
|
209
|
+
createMockTuitionFee('general', 20000, 'GBP') // Add tuition fees
|
|
210
|
+
]),
|
|
211
|
+
canShowTimings: vi.fn().mockReturnValue(false), // No timing data
|
|
212
|
+
getTimings: vi.fn().mockReturnValue([]),
|
|
213
|
+
isFullTime: vi.fn().mockReturnValue(true),
|
|
214
|
+
isPartTime: vi.fn().mockReturnValue(false),
|
|
215
|
+
isOnCampus: vi.fn().mockReturnValue(false),
|
|
216
|
+
isOnline: vi.fn().mockReturnValue(false),
|
|
217
|
+
isBlended: vi.fn().mockReturnValue(true),
|
|
218
|
+
// Add missing required properties with sensible defaults
|
|
219
|
+
getCountryIsoCode: vi.fn().mockReturnValue('US'),
|
|
220
|
+
getCover: vi.fn().mockReturnValue(null),
|
|
221
|
+
canShowCover: vi.fn().mockReturnValue(false),
|
|
222
|
+
getDegree: vi.fn().mockReturnValue(null),
|
|
223
|
+
getUniversity: vi.fn().mockReturnValue(null),
|
|
224
|
+
getCity: vi.fn().mockReturnValue(null),
|
|
225
|
+
getCountry: vi.fn().mockReturnValue(null),
|
|
226
|
+
getContinent: vi.fn().mockReturnValue(null),
|
|
227
|
+
getDiscipline: vi.fn().mockReturnValue(null),
|
|
228
|
+
getArea: vi.fn().mockReturnValue(null),
|
|
229
|
+
getSpecialProgrammes: vi.fn().mockReturnValue([]),
|
|
230
|
+
getEducationalForm: vi.fn().mockReturnValue(null),
|
|
231
|
+
getFormat: vi.fn().mockReturnValue(null),
|
|
232
|
+
getDuration: vi.fn().mockReturnValue(null),
|
|
233
|
+
getLanguage: vi.fn().mockReturnValue(null),
|
|
234
|
+
canShowTuitionFees: vi.fn().mockReturnValue(true), // Change to true since it now has fees
|
|
235
|
+
getApplicationFees: vi.fn().mockReturnValue([]),
|
|
236
|
+
canShowApplicationFees: vi.fn().mockReturnValue(false),
|
|
237
|
+
getFees: vi.fn().mockReturnValue([]),
|
|
238
|
+
canShowFees: vi.fn().mockReturnValue(false),
|
|
239
|
+
getScholarships: vi.fn().mockReturnValue([]),
|
|
240
|
+
canShowScholarships: vi.fn().mockReturnValue(false),
|
|
241
|
+
canShowReviewRating: vi.fn().mockReturnValue(true),
|
|
242
|
+
getCredentials: vi.fn().mockReturnValue([]),
|
|
243
|
+
canShowCredentials: vi.fn().mockReturnValue(false),
|
|
244
|
+
getDeadlines: vi.fn().mockReturnValue([]),
|
|
245
|
+
canShowDeadlines: vi.fn().mockReturnValue(false),
|
|
246
|
+
getRequirements: vi.fn().mockReturnValue([]),
|
|
247
|
+
canShowRequirements: vi.fn().mockReturnValue(false),
|
|
248
|
+
getAttendance: vi.fn().mockReturnValue(null),
|
|
249
|
+
isDistance: vi.fn().mockReturnValue(false)
|
|
250
|
+
};
|
|
251
|
+
return [card1, card2, card3];
|
|
252
|
+
}
|
|
253
|
+
describe('buildStructuredData - Main Public Interface', () => {
|
|
254
|
+
it('should generate complete structured data with all components', async () => {
|
|
255
|
+
const result = await factory.buildStructuredData('Computer Science Programs', 'Find the best computer science programs worldwide', mockProgrammeCards, mockFaqItems, mockBreadcrumbs);
|
|
256
|
+
// Basic structure
|
|
257
|
+
expect(result['@context']).toBe('https://schema.org');
|
|
258
|
+
expect(result['@type']).toBe('SearchResultsPage');
|
|
259
|
+
expect(result.name).toBe('Computer Science Programs');
|
|
260
|
+
expect(result.description).toBe('Find the best computer science programs worldwide');
|
|
261
|
+
expect(result.mainEntity).toHaveLength(3); // All 3 cards now have tuition fees
|
|
262
|
+
});
|
|
263
|
+
it('should generate structured data with empty arrays gracefully', async () => {
|
|
264
|
+
const result = await factory.buildStructuredData('Empty Results', 'No programs found', [], [], []);
|
|
265
|
+
expect(result.mainEntity).toHaveLength(0);
|
|
266
|
+
expect(result.aggregateRating).toBeUndefined();
|
|
267
|
+
expect(result.offers).toBeUndefined();
|
|
268
|
+
expect(result.hasPart).toBeUndefined();
|
|
269
|
+
expect(result.breadcrumb).toBeUndefined();
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
describe('Course Structured Data Generation', () => {
|
|
273
|
+
it('should generate correct Course structured data for full-time on-campus program', async () => {
|
|
274
|
+
const result = await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[0]], [], []);
|
|
275
|
+
const course = result.mainEntity[0];
|
|
276
|
+
expect(course['@type']).toBe('Course');
|
|
277
|
+
expect(course.name).toBe('Master of Computer Science');
|
|
278
|
+
expect(course.description).toBe('Advanced computer science program focusing on AI and machine learning.');
|
|
279
|
+
expect(course.url).toBe('/programmes/master-computer-science');
|
|
280
|
+
// Provider information
|
|
281
|
+
expect(course.provider?.['@type']).toBe('EducationalOrganization');
|
|
282
|
+
expect(course.provider?.name).toBe('Tech University');
|
|
283
|
+
expect(course.provider?.url).toBe('https://studyportals.com/universities/tech-university');
|
|
284
|
+
// Course instance
|
|
285
|
+
expect(course.hasCourseInstance?.['@type']).toBe('CourseInstance');
|
|
286
|
+
expect(course.hasCourseInstance?.courseMode).toBe('onsite');
|
|
287
|
+
expect(course.hasCourseInstance?.courseWorkload).toBe('PT40H');
|
|
288
|
+
expect(course.hasCourseInstance?.startDate).toBe('2024-09-01');
|
|
289
|
+
});
|
|
290
|
+
it('should generate correct Course structured data for part-time online program', async () => {
|
|
291
|
+
const result = await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[1]], [], []);
|
|
292
|
+
const course = result.mainEntity[0];
|
|
293
|
+
expect(course.name).toBe('MBA in Digital Marketing');
|
|
294
|
+
expect(course.hasCourseInstance?.courseMode).toBe('online');
|
|
295
|
+
expect(course.hasCourseInstance?.courseWorkload).toBe('PT20H');
|
|
296
|
+
expect(course.hasCourseInstance?.startDate).toBe('2024-10-01');
|
|
297
|
+
});
|
|
298
|
+
it('should generate correct Course structured data for blended program', async () => {
|
|
299
|
+
const result = await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[2]], [], []);
|
|
300
|
+
const course = result.mainEntity[0];
|
|
301
|
+
expect(course.name).toBe('Bachelor of Engineering');
|
|
302
|
+
expect(course.hasCourseInstance?.courseMode).toBe('blended');
|
|
303
|
+
expect(course.hasCourseInstance?.courseWorkload).toBe('PT40H');
|
|
304
|
+
expect(course.hasCourseInstance?.startDate).toBeUndefined();
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
describe('Rating Integration', () => {
|
|
308
|
+
it('should include aggregate rating when cards have ratings', async () => {
|
|
309
|
+
const result = await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[0]], [], []);
|
|
310
|
+
const course = result.mainEntity[0];
|
|
311
|
+
expect(course.aggregateRating?.['@type']).toBe('AggregateRating');
|
|
312
|
+
expect(course.aggregateRating?.ratingValue).toBe(4.5);
|
|
313
|
+
expect(course.aggregateRating?.ratingCount).toBe(120);
|
|
314
|
+
expect(course.aggregateRating?.bestRating).toBe(5);
|
|
315
|
+
expect(course.aggregateRating?.worstRating).toBe(1);
|
|
316
|
+
});
|
|
317
|
+
it('should not include aggregate rating when card has no ratings', async () => {
|
|
318
|
+
const result = await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[1]], [], []);
|
|
319
|
+
const course = result.mainEntity[0];
|
|
320
|
+
expect(course.aggregateRating).toBeUndefined();
|
|
321
|
+
});
|
|
322
|
+
it('should not include aggregate rating when hasEnoughQuantity is false', async () => {
|
|
323
|
+
// Create a mock review rating with hasEnoughQuantity returning false
|
|
324
|
+
const createMockReviewRatingInsufficient = (avgRating, quantity) => ({
|
|
325
|
+
getAverageStarRating: vi.fn().mockReturnValue(avgRating),
|
|
326
|
+
getQuantity: vi.fn().mockReturnValue(quantity),
|
|
327
|
+
getAverage: vi.fn().mockReturnValue(avgRating),
|
|
328
|
+
hasEnoughQuantity: vi.fn().mockReturnValue(false) // This should prevent rating from being included
|
|
329
|
+
});
|
|
330
|
+
// Create a mock card with insufficient rating quantity
|
|
331
|
+
const cardWithInsufficientRating = {
|
|
332
|
+
...mockProgrammeCards[0],
|
|
333
|
+
getReviewRating: vi.fn().mockReturnValue(createMockReviewRatingInsufficient(4.2, 3)), // Low quantity
|
|
334
|
+
canShowReviewRating: vi.fn().mockReturnValue(true)
|
|
335
|
+
};
|
|
336
|
+
const result = await factory.buildStructuredData('Test', 'Test', [cardWithInsufficientRating], [], []);
|
|
337
|
+
const course = result.mainEntity[0];
|
|
338
|
+
// Should not include aggregate rating when hasEnoughQuantity is false
|
|
339
|
+
expect(course.aggregateRating).toBeUndefined();
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
describe('Offer Integration', () => {
|
|
343
|
+
it('should include offer when card has tuition fees', async () => {
|
|
344
|
+
const result = await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[0]], [], []);
|
|
345
|
+
const course = result.mainEntity[0];
|
|
346
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(30000, 'EUR', 'USD');
|
|
347
|
+
expect(course.offers?.['@type']).toBe('Offer');
|
|
348
|
+
expect(course.offers?.price).toBe(25000);
|
|
349
|
+
expect(course.offers?.priceCurrency).toBe('USD');
|
|
350
|
+
expect(course.offers?.category).toBe('tuition');
|
|
351
|
+
expect(course.offers?.validFrom).toBe('2024-09-01');
|
|
352
|
+
});
|
|
353
|
+
it('should prioritize international tuition fees over other types', async () => {
|
|
354
|
+
await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[0]], [], []);
|
|
355
|
+
// Should call with international fee (30000 EUR) not national fee (15000 EUR)
|
|
356
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(30000, 'EUR', 'USD');
|
|
357
|
+
});
|
|
358
|
+
it('should calculate page-level aggregate offer from multiple cards', async () => {
|
|
359
|
+
const cardsWithOffers = [mockProgrammeCards[0], mockProgrammeCards[1]]; // Card 2 has no fees
|
|
360
|
+
const result = await factory.buildStructuredData('Test', 'Test', cardsWithOffers, [], []);
|
|
361
|
+
expect(result.offers?.['@type']).toBe('AggregateOffer');
|
|
362
|
+
expect(result.offers?.priceCurrency).toBe('USD');
|
|
363
|
+
expect(result.offers?.offerCount).toBe(2);
|
|
364
|
+
expect(result.offers?.lowPrice).toBe(25000);
|
|
365
|
+
expect(result.offers?.highPrice).toBe(25000);
|
|
366
|
+
});
|
|
367
|
+
it('should set minPrice to 0 in page-level aggregate offer when free tuition fee is detected', async () => {
|
|
368
|
+
// Create a mock card with free tuition fee
|
|
369
|
+
const createMockTuitionFee = (target, amount, currency) => ({
|
|
370
|
+
getTarget: vi.fn().mockReturnValue(target),
|
|
371
|
+
getAmount: vi.fn().mockReturnValue(amount),
|
|
372
|
+
getCurrency: vi.fn().mockReturnValue(currency),
|
|
373
|
+
getOriginalAmount: vi.fn().mockReturnValue(amount),
|
|
374
|
+
getOriginalUnit: vi.fn().mockReturnValue(currency),
|
|
375
|
+
getUnit: vi.fn().mockReturnValue(currency),
|
|
376
|
+
isFree: vi.fn().mockReturnValue(amount === 0)
|
|
377
|
+
});
|
|
378
|
+
const createMockLink = (url, description) => ({
|
|
379
|
+
getUrl: vi.fn().mockReturnValue(url),
|
|
380
|
+
getDescription: vi.fn().mockReturnValue(description),
|
|
381
|
+
canShowDescription: vi.fn().mockReturnValue(true)
|
|
382
|
+
});
|
|
383
|
+
const freeCard = {
|
|
384
|
+
...mockProgrammeCards[0],
|
|
385
|
+
getTitle: vi.fn().mockReturnValue('Free Online Course'),
|
|
386
|
+
getProgrammeLink: vi.fn().mockReturnValue(createMockLink('/programmes/free-course', 'Free Online Course')),
|
|
387
|
+
getTuitionFees: vi.fn().mockReturnValue([
|
|
388
|
+
createMockTuitionFee('general', 0, 'USD') // Free tuition
|
|
389
|
+
])
|
|
390
|
+
};
|
|
391
|
+
// Mock currency service to return 0 for free course and 25000 for paid course
|
|
392
|
+
mockCurrencyService.convert = vi.fn()
|
|
393
|
+
.mockImplementation((amount) => Promise.resolve(amount === 0 ? 0 : 25000));
|
|
394
|
+
const cardsWithFreeAndPaid = [mockProgrammeCards[0], freeCard]; // One paid, one free
|
|
395
|
+
const result = await factory.buildStructuredData('Test', 'Test', cardsWithFreeAndPaid, [], []);
|
|
396
|
+
expect(result.offers?.['@type']).toBe('AggregateOffer');
|
|
397
|
+
expect(result.offers?.priceCurrency).toBe('USD');
|
|
398
|
+
expect(result.offers?.offerCount).toBe(2);
|
|
399
|
+
expect(result.offers?.lowPrice).toBe(0); // Should be 0 due to free course
|
|
400
|
+
expect(result.offers?.highPrice).toBe(25000);
|
|
401
|
+
// Verify currency conversion was called for both cards
|
|
402
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(30000, 'EUR', 'USD'); // Paid course
|
|
403
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(0, 'USD', 'USD'); // Free course
|
|
404
|
+
});
|
|
405
|
+
it('should exclude cards with no tuition fees from mainEntity object', async () => {
|
|
406
|
+
// Create a new card with no tuition fees for this specific test
|
|
407
|
+
const createMockLink = (url, description) => ({
|
|
408
|
+
getUrl: vi.fn().mockReturnValue(url),
|
|
409
|
+
getDescription: vi.fn().mockReturnValue(description),
|
|
410
|
+
canShowDescription: vi.fn().mockReturnValue(true)
|
|
411
|
+
});
|
|
412
|
+
const cardWithoutFees = {
|
|
413
|
+
...mockProgrammeCards[0],
|
|
414
|
+
getTitle: vi.fn().mockReturnValue('Free Certificate Program'),
|
|
415
|
+
getProgrammeLink: vi.fn().mockReturnValue(createMockLink('/programmes/free-certificate', 'Free Certificate Program')),
|
|
416
|
+
getTuitionFees: vi.fn().mockReturnValue([]), // No tuition fees
|
|
417
|
+
canShowTuitionFees: vi.fn().mockReturnValue(false),
|
|
418
|
+
};
|
|
419
|
+
// Use card with tuition fees and card without tuition fees
|
|
420
|
+
const cardsWithAndWithoutFees = [mockProgrammeCards[0], cardWithoutFees]; // Card 1 has fees, new card has no fees
|
|
421
|
+
const result = await factory.buildStructuredData('Test', 'Test', cardsWithAndWithoutFees, [], []);
|
|
422
|
+
// Should only include the card with tuition fees in mainEntity
|
|
423
|
+
expect(result.mainEntity).toHaveLength(1);
|
|
424
|
+
expect(result.mainEntity?.[0]?.name).toBe('Master of Computer Science'); // Only card 1 should be included
|
|
425
|
+
// The aggregate offer should still be created but only for cards with fees
|
|
426
|
+
expect(result.offers?.['@type']).toBe('AggregateOffer');
|
|
427
|
+
expect(result.offers?.offerCount).toBe(1); // Only one card with fees
|
|
428
|
+
expect(result.offers?.lowPrice).toBe(25000);
|
|
429
|
+
expect(result.offers?.highPrice).toBe(25000);
|
|
430
|
+
// Verify currency conversion was only called for the card with fees
|
|
431
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(30000, 'EUR', 'USD'); // Card 1 with fees
|
|
432
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledTimes(1); // Should only be called once
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
describe('FAQ Integration', () => {
|
|
436
|
+
it('should include FAQ page when FAQ items are provided', async () => {
|
|
437
|
+
const result = await factory.buildStructuredData('Test', 'Test', [], mockFaqItems, []);
|
|
438
|
+
expect(result.hasPart?.['@type']).toBe('FAQPage');
|
|
439
|
+
expect(result.hasPart?.mainEntity).toHaveLength(2);
|
|
440
|
+
const firstQuestion = result.hasPart?.mainEntity?.[0];
|
|
441
|
+
expect(firstQuestion?.['@type']).toBe('Question');
|
|
442
|
+
expect(firstQuestion?.name).toBe('What are the admission requirements?');
|
|
443
|
+
expect(firstQuestion?.acceptedAnswer?.['@type']).toBe('Answer');
|
|
444
|
+
expect(firstQuestion?.acceptedAnswer?.text).toContain('bachelor\'s degree');
|
|
445
|
+
});
|
|
446
|
+
it('should not include FAQ page when no FAQ items provided', async () => {
|
|
447
|
+
const result = await factory.buildStructuredData('Test', 'Test', [], [], []);
|
|
448
|
+
expect(result.hasPart).toBeUndefined();
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
describe('Breadcrumb Integration', () => {
|
|
452
|
+
it('should include breadcrumb list when breadcrumbs are provided', async () => {
|
|
453
|
+
const result = await factory.buildStructuredData('Test', 'Test', [], [], mockBreadcrumbs);
|
|
454
|
+
expect(result.breadcrumb?.['@type']).toBe('BreadcrumbList');
|
|
455
|
+
expect(result.breadcrumb?.itemListElement).toHaveLength(3);
|
|
456
|
+
const firstBreadcrumb = result.breadcrumb?.itemListElement?.[0];
|
|
457
|
+
expect(firstBreadcrumb?.['@type']).toBe('ListItem');
|
|
458
|
+
expect(firstBreadcrumb?.name).toBe('Home');
|
|
459
|
+
expect(firstBreadcrumb?.position).toBe(1);
|
|
460
|
+
expect(firstBreadcrumb?.item).toBe('https://localhost:8080/');
|
|
461
|
+
});
|
|
462
|
+
it('should not include breadcrumb list when no breadcrumbs provided', async () => {
|
|
463
|
+
const result = await factory.buildStructuredData('Test', 'Test', [], [], []);
|
|
464
|
+
expect(result.breadcrumb).toBeUndefined();
|
|
465
|
+
});
|
|
466
|
+
});
|
|
467
|
+
describe('Currency Conversion Service Integration', () => {
|
|
468
|
+
it('should call currency conversion service for each card with tuition fees', async () => {
|
|
469
|
+
await factory.buildStructuredData('Test', 'Test', mockProgrammeCards, [], []);
|
|
470
|
+
// Should be called three times: once for each card (all cards now have fees)
|
|
471
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledTimes(3);
|
|
472
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(30000, 'EUR', 'USD'); // Card 1
|
|
473
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(45000, 'USD', 'USD'); // Card 2
|
|
474
|
+
expect(mockCurrencyService.convert).toHaveBeenCalledWith(20000, 'GBP', 'USD'); // Card 3
|
|
475
|
+
});
|
|
476
|
+
it('should handle currency conversion errors gracefully', async () => {
|
|
477
|
+
mockCurrencyService.convert = vi.fn().mockRejectedValue(new Error('Conversion failed'));
|
|
478
|
+
// The method should handle the error and continue processing
|
|
479
|
+
await expect(async () => {
|
|
480
|
+
await factory.buildStructuredData('Test', 'Test', [mockProgrammeCards[0]], [], []);
|
|
481
|
+
}).rejects.toThrow('Conversion failed');
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
describe('Edge Cases and Error Handling', () => {
|
|
485
|
+
it('should handle cards with no timing data', async () => {
|
|
486
|
+
const cardWithoutTimings = {
|
|
487
|
+
...mockProgrammeCards[0],
|
|
488
|
+
canShowTimings: vi.fn().mockReturnValue(false),
|
|
489
|
+
getTimings: vi.fn().mockReturnValue([])
|
|
490
|
+
};
|
|
491
|
+
const result = await factory.buildStructuredData('Test', 'Test', [cardWithoutTimings], [], []);
|
|
492
|
+
const course = result.mainEntity[0];
|
|
493
|
+
expect(course.hasCourseInstance?.startDate).toBeUndefined();
|
|
494
|
+
expect(course.offers?.validFrom).toBeUndefined();
|
|
495
|
+
});
|
|
496
|
+
it('should handle cards with mixed course modes', async () => {
|
|
497
|
+
const mixedModeCard = {
|
|
498
|
+
...mockProgrammeCards[0],
|
|
499
|
+
isFullTime: vi.fn().mockReturnValue(false),
|
|
500
|
+
isPartTime: vi.fn().mockReturnValue(false),
|
|
501
|
+
isOnCampus: vi.fn().mockReturnValue(false),
|
|
502
|
+
isOnline: vi.fn().mockReturnValue(false),
|
|
503
|
+
isBlended: vi.fn().mockReturnValue(false)
|
|
504
|
+
};
|
|
505
|
+
const result = await factory.buildStructuredData('Test', 'Test', [mixedModeCard], [], []);
|
|
506
|
+
const course = result.mainEntity[0];
|
|
507
|
+
expect(course.hasCourseInstance?.courseMode).toBeUndefined();
|
|
508
|
+
expect(course.hasCourseInstance?.courseWorkload).toBeUndefined();
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
describe('Basic Schema Structure Validation', () => {
|
|
512
|
+
it('should generate structured data with required schema.org fields', async () => {
|
|
513
|
+
const result = await factory.buildStructuredData('Computer Science Programs', 'Find the best computer science programs worldwide', mockProgrammeCards, mockFaqItems, mockBreadcrumbs);
|
|
514
|
+
// Validate basic structure
|
|
515
|
+
expect(result['@context']).toBe('https://schema.org');
|
|
516
|
+
expect(result['@type']).toBe('SearchResultsPage');
|
|
517
|
+
expect(result.name).toBeDefined();
|
|
518
|
+
expect(result.description).toBeDefined();
|
|
519
|
+
expect(Array.isArray(result.mainEntity)).toBe(true);
|
|
520
|
+
});
|
|
521
|
+
it('should generate minimal valid structured data', async () => {
|
|
522
|
+
const result = await factory.buildStructuredData('Test', 'Test Description', [], [], []);
|
|
523
|
+
expect(result['@context']).toBe('https://schema.org');
|
|
524
|
+
expect(result['@type']).toBe('SearchResultsPage');
|
|
525
|
+
expect(result.name).toBe('Test');
|
|
526
|
+
expect(result.description).toBe('Test Description');
|
|
527
|
+
expect(result.mainEntity).toEqual([]);
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
describe('Schema Validation', () => {
|
|
531
|
+
it('should generate valid structured data for complete scenario', async () => {
|
|
532
|
+
const result = await factory.buildStructuredData('Computer Science Programs', 'Find the best computer science programs worldwide', mockProgrammeCards, mockFaqItems, mockBreadcrumbs);
|
|
533
|
+
// Validate against schema.org standards using Adobe validator
|
|
534
|
+
const validationResults = await validator.validate({ jsonld: { SearchResultsPage: [result] } });
|
|
535
|
+
expect(validationResults.filter((issue) => issue.severity === 'ERROR')).toHaveLength(0); // No validation errors
|
|
536
|
+
});
|
|
537
|
+
it('should generate valid structured data for minimal scenario', async () => {
|
|
538
|
+
const result = await factory.buildStructuredData('Test', 'Test Description', [], [], []);
|
|
539
|
+
// Validate against schema.org standards using Adobe validator
|
|
540
|
+
const validationResults = await validator.validate({ jsonld: { SearchResultsPage: [result] } });
|
|
541
|
+
expect(validationResults).toHaveLength(0); // No validation errors
|
|
542
|
+
});
|
|
543
|
+
it('should generate valid structured data with only programme cards', async () => {
|
|
544
|
+
const result = await factory.buildStructuredData('Programme Cards Only', 'Testing with programme cards only', mockProgrammeCards, [], []);
|
|
545
|
+
// Validate against schema.org standards using Adobe validator
|
|
546
|
+
const validationResults = await validator.validate({ jsonld: { SearchResultsPage: [result] } });
|
|
547
|
+
expect(validationResults.filter((issue) => issue.severity === 'ERROR')).toHaveLength(0); // No validation errors
|
|
548
|
+
});
|
|
549
|
+
it('should generate valid structured data with only FAQ items', async () => {
|
|
550
|
+
const result = await factory.buildStructuredData('FAQ Only', 'Testing with FAQ items only', [], mockFaqItems, []);
|
|
551
|
+
// Validate against schema.org standards using Adobe validator
|
|
552
|
+
const validationResults = await validator.validate({ jsonld: { SearchResultsPage: [result] } });
|
|
553
|
+
expect(validationResults).toHaveLength(0); // No validation errors
|
|
554
|
+
});
|
|
555
|
+
it('should generate valid structured data with only breadcrumbs', async () => {
|
|
556
|
+
const result = await factory.buildStructuredData('Breadcrumbs Only', 'Testing with breadcrumbs only', [], [], mockBreadcrumbs);
|
|
557
|
+
// Validate against schema.org standards using Adobe validator
|
|
558
|
+
const validationResults = await validator.validate({ jsonld: { SearchResultsPage: [result] } });
|
|
559
|
+
expect(validationResults.filter((issue) => issue.severity === 'ERROR')).toHaveLength(0); // No validation errors
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|