@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.
Files changed (520) hide show
  1. package/dist/organisations-seo/index.d.ts +3 -3
  2. package/dist/organisations-seo/index.js +1 -1
  3. package/dist/programmes-seo/index.d.ts +5 -5
  4. package/dist/programmes-seo/index.js +1 -1
  5. package/dist/scholarships-seo/index.d.ts +4 -4
  6. package/dist/scholarships-seo/index.js +2 -2
  7. package/dist/sitemap-generator-seo/index.d.ts +14 -14
  8. package/dist/sitemap-generator-seo/index.js +5 -5
  9. package/dist/src/common/IDependencies.d.ts +1 -1
  10. package/dist/src/common/IPresenter.d.ts +1 -1
  11. package/dist/src/common/ISearchDependencies.d.ts +1 -1
  12. package/dist/src/common/ISeoDependencies.d.ts +2 -2
  13. package/dist/src/common/ISitemapDependencies.d.ts +2 -2
  14. package/dist/src/common/ISitemapUrlGenerator.d.ts +1 -1
  15. package/dist/src/common/policies/BaseSeoIndexabilityPolicy.d.ts +1 -1
  16. package/dist/src/common/policies/BaseSeoIndexabilityPolicy.js +2 -2
  17. package/dist/src/common/rules/NoFiltersSelectedRule.d.ts +2 -2
  18. package/dist/src/common/rules/OnlineAttendanceRule.d.ts +1 -1
  19. package/dist/src/common/rules/OnlineAttendanceRule.js +1 -1
  20. package/dist/src/common/rules/OnlyFiltersSelectedRule.d.ts +2 -2
  21. package/dist/src/common/rules/SingleValueSelectedForFilterRule.d.ts +2 -2
  22. package/dist/src/organisations/IOrganisationSearchApplicationState.d.ts +1 -1
  23. package/dist/src/organisations/ISeoSortingState.d.ts +1 -1
  24. package/dist/src/organisations/SearchIndexabilityManager.d.ts +4 -4
  25. package/dist/src/organisations/SearchIndexabilityManager.js +2 -2
  26. package/dist/src/organisations/policies/OrganisationsSeoIndexabilityPolicy.d.ts +3 -3
  27. package/dist/src/organisations/policies/OrganisationsSeoIndexabilityPolicy.js +3 -3
  28. package/dist/src/organisations/policies/RankedOrganisationsSeoIndexabilityPolicy.d.ts +1 -1
  29. package/dist/src/organisations/policies/RankedOrganisationsSeoIndexabilityPolicy.js +1 -1
  30. package/dist/src/organisations/policies/our-picks/Area.d.ts +5 -5
  31. package/dist/src/organisations/policies/our-picks/Area.js +6 -6
  32. package/dist/src/organisations/policies/our-picks/AreaAttendance.d.ts +7 -7
  33. package/dist/src/organisations/policies/our-picks/AreaAttendance.js +9 -9
  34. package/dist/src/organisations/policies/our-picks/Attendance.d.ts +6 -6
  35. package/dist/src/organisations/policies/our-picks/Attendance.js +7 -7
  36. package/dist/src/organisations/policies/our-picks/Continent.d.ts +5 -5
  37. package/dist/src/organisations/policies/our-picks/Continent.js +6 -6
  38. package/dist/src/organisations/policies/our-picks/Country.d.ts +5 -5
  39. package/dist/src/organisations/policies/our-picks/Country.js +6 -6
  40. package/dist/src/organisations/policies/our-picks/CountryAreaCity.d.ts +6 -6
  41. package/dist/src/organisations/policies/our-picks/CountryAreaCity.js +7 -7
  42. package/dist/src/organisations/policies/our-picks/CountryAttendance.d.ts +7 -7
  43. package/dist/src/organisations/policies/our-picks/CountryAttendance.js +9 -9
  44. package/dist/src/organisations/policies/our-picks/CountryCity.d.ts +6 -6
  45. package/dist/src/organisations/policies/our-picks/CountryCity.js +7 -7
  46. package/dist/src/organisations/policies/our-picks/Unfiltered.d.ts +4 -4
  47. package/dist/src/organisations/policies/our-picks/Unfiltered.js +4 -4
  48. package/dist/src/organisations/policies/ranked/RankedArea.d.ts +4 -4
  49. package/dist/src/organisations/policies/ranked/RankedArea.js +4 -4
  50. package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.d.ts +5 -5
  51. package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.js +6 -6
  52. package/dist/src/organisations/policies/ranked/RankedAttendance.d.ts +5 -5
  53. package/dist/src/organisations/policies/ranked/RankedAttendance.js +5 -5
  54. package/dist/src/organisations/policies/ranked/RankedAttendanceDiscipline.d.ts +5 -5
  55. package/dist/src/organisations/policies/ranked/RankedAttendanceDiscipline.js +6 -6
  56. package/dist/src/organisations/policies/ranked/RankedContinent.d.ts +4 -4
  57. package/dist/src/organisations/policies/ranked/RankedContinent.js +4 -4
  58. package/dist/src/organisations/policies/ranked/RankedContinentAttendance.d.ts +6 -6
  59. package/dist/src/organisations/policies/ranked/RankedContinentAttendance.js +7 -7
  60. package/dist/src/organisations/policies/ranked/RankedCountry.d.ts +4 -4
  61. package/dist/src/organisations/policies/ranked/RankedCountry.js +4 -4
  62. package/dist/src/organisations/policies/ranked/RankedCountryAttendance.d.ts +5 -5
  63. package/dist/src/organisations/policies/ranked/RankedCountryAttendance.js +6 -6
  64. package/dist/src/organisations/policies/ranked/RankedCountryDiscipline.d.ts +4 -4
  65. package/dist/src/organisations/policies/ranked/RankedCountryDiscipline.js +5 -5
  66. package/dist/src/organisations/policies/ranked/RankedDiscipline.d.ts +4 -4
  67. package/dist/src/organisations/policies/ranked/RankedDiscipline.js +4 -4
  68. package/dist/src/organisations/policies/ranked/RankedUnfiltered.d.ts +3 -3
  69. package/dist/src/organisations/policies/ranked/RankedUnfiltered.js +2 -2
  70. package/dist/src/organisations/rules/BaseSearchVolumeOrganisationsRule.d.ts +3 -3
  71. package/dist/src/organisations/rules/ContinentIsEuropeRule.d.ts +1 -1
  72. package/dist/src/organisations/rules/ContinentIsEuropeRule.js +1 -1
  73. package/dist/src/organisations/rules/ExcludeByIdForCitiesRule.d.ts +3 -3
  74. package/dist/src/organisations/rules/MinimumAmountOfRankedResultsRule.d.ts +3 -3
  75. package/dist/src/organisations/rules/MinimumAmountOfRankedResultsRule.js +1 -1
  76. package/dist/src/organisations/rules/MinimumAmountOfResultsRule.d.ts +4 -4
  77. package/dist/src/organisations/rules/MinimumAmountOfResultsRule.js +1 -1
  78. package/dist/src/organisations/rules/NoFiltersSelectedRule.d.ts +2 -2
  79. package/dist/src/organisations/types/IOrganisationSearchDependencies.d.ts +2 -2
  80. package/dist/src/organisations/types/IOrganisationsSitemapDependencies.d.ts +3 -3
  81. package/dist/src/presenters/AreaPresenter.d.ts +1 -1
  82. package/dist/src/presenters/AttendancePresenter.d.ts +1 -1
  83. package/dist/src/presenters/CityPresenter.d.ts +1 -1
  84. package/dist/src/presenters/ContinentPresenter.d.ts +1 -1
  85. package/dist/src/presenters/CountryPresenter.d.ts +1 -1
  86. package/dist/src/presenters/DegreePresenter.d.ts +1 -1
  87. package/dist/src/presenters/DisciplinePresenter.d.ts +1 -1
  88. package/dist/src/presenters/DurationPresenter.d.ts +1 -1
  89. package/dist/src/presenters/EducationalFormPresenter.d.ts +1 -1
  90. package/dist/src/presenters/FormatPresenter.d.ts +1 -1
  91. package/dist/src/presenters/SpecialProgrammesPresenter.d.ts +1 -1
  92. package/dist/src/presenters/TuitionFeePresenter.d.ts +1 -1
  93. package/dist/src/programmes/BaseProgrammeFilterKeyValueRule.d.ts +2 -2
  94. package/dist/src/programmes/BaseProgrammeFilterKeyValueRule.js +1 -1
  95. package/dist/src/programmes/BaseProgrammeRule.d.ts +2 -2
  96. package/dist/src/programmes/IProgrammeRule.d.ts +2 -2
  97. package/dist/src/programmes/ProgrammesBaseIndexabilityPolicy.d.ts +3 -3
  98. package/dist/src/programmes/ProgrammesBaseIndexabilityPolicy.js +1 -1
  99. package/dist/src/programmes/SearchIndexabilityManager.d.ts +4 -4
  100. package/dist/src/programmes/SearchIndexabilityManager.js +8 -4
  101. package/dist/src/programmes/policies/Area.d.ts +3 -3
  102. package/dist/src/programmes/policies/Area.js +4 -4
  103. package/dist/src/programmes/policies/Attendance.d.ts +4 -4
  104. package/dist/src/programmes/policies/Attendance.js +5 -5
  105. package/dist/src/programmes/policies/AttendanceArea.d.ts +4 -4
  106. package/dist/src/programmes/policies/AttendanceArea.js +6 -6
  107. package/dist/src/programmes/policies/AttendanceContinent.d.ts +4 -4
  108. package/dist/src/programmes/policies/AttendanceContinent.js +6 -6
  109. package/dist/src/programmes/policies/AttendanceDegree.d.ts +2 -2
  110. package/dist/src/programmes/policies/AttendanceDegree.js +5 -5
  111. package/dist/src/programmes/policies/AttendanceDuration.d.ts +5 -5
  112. package/dist/src/programmes/policies/AttendanceDuration.js +7 -7
  113. package/dist/src/programmes/policies/AttendanceFormat.d.ts +4 -4
  114. package/dist/src/programmes/policies/AttendanceFormat.js +6 -6
  115. package/dist/src/programmes/policies/Continent.d.ts +3 -3
  116. package/dist/src/programmes/policies/Continent.js +4 -4
  117. package/dist/src/programmes/policies/ContinentDuration.d.ts +3 -3
  118. package/dist/src/programmes/policies/ContinentDuration.js +5 -5
  119. package/dist/src/programmes/policies/ContinentFormat.d.ts +3 -3
  120. package/dist/src/programmes/policies/ContinentFormat.js +5 -5
  121. package/dist/src/programmes/policies/ContinentSpecialProgrammes.d.ts +4 -4
  122. package/dist/src/programmes/policies/ContinentSpecialProgrammes.js +6 -6
  123. package/dist/src/programmes/policies/Country.d.ts +3 -3
  124. package/dist/src/programmes/policies/Country.js +4 -4
  125. package/dist/src/programmes/policies/CountryAttendance.d.ts +4 -4
  126. package/dist/src/programmes/policies/CountryAttendance.js +6 -6
  127. package/dist/src/programmes/policies/CountryAttendanceDegree.d.ts +4 -4
  128. package/dist/src/programmes/policies/CountryAttendanceDegree.js +7 -7
  129. package/dist/src/programmes/policies/CountryDegree.d.ts +2 -2
  130. package/dist/src/programmes/policies/CountryDegree.js +5 -5
  131. package/dist/src/programmes/policies/CountryDuration.d.ts +3 -3
  132. package/dist/src/programmes/policies/CountryDuration.js +5 -5
  133. package/dist/src/programmes/policies/CountryDurationDegree.d.ts +3 -3
  134. package/dist/src/programmes/policies/CountryDurationDegree.js +6 -6
  135. package/dist/src/programmes/policies/CountryEducationalForm.d.ts +2 -2
  136. package/dist/src/programmes/policies/CountryEducationalForm.js +5 -5
  137. package/dist/src/programmes/policies/CountryFormat.d.ts +3 -3
  138. package/dist/src/programmes/policies/CountryFormat.js +5 -5
  139. package/dist/src/programmes/policies/CountrySpecialProgrammes.d.ts +4 -4
  140. package/dist/src/programmes/policies/CountrySpecialProgrammes.js +6 -6
  141. package/dist/src/programmes/policies/Degree.d.ts +3 -3
  142. package/dist/src/programmes/policies/Degree.js +4 -4
  143. package/dist/src/programmes/policies/DegreeArea.d.ts +3 -3
  144. package/dist/src/programmes/policies/DegreeArea.js +5 -5
  145. package/dist/src/programmes/policies/DegreeAttendanceDiscipline.d.ts +4 -4
  146. package/dist/src/programmes/policies/DegreeAttendanceDiscipline.js +7 -7
  147. package/dist/src/programmes/policies/DegreeAttendanceFormat.d.ts +4 -4
  148. package/dist/src/programmes/policies/DegreeAttendanceFormat.js +7 -7
  149. package/dist/src/programmes/policies/DegreeAttendanceSpecialProgrammes.d.ts +4 -4
  150. package/dist/src/programmes/policies/DegreeAttendanceSpecialProgrammes.js +7 -7
  151. package/dist/src/programmes/policies/DegreeContinent.d.ts +2 -2
  152. package/dist/src/programmes/policies/DegreeContinent.js +5 -5
  153. package/dist/src/programmes/policies/DegreeCountryAttendance.d.ts +3 -3
  154. package/dist/src/programmes/policies/DegreeCountryAttendance.js +6 -6
  155. package/dist/src/programmes/policies/DegreeCountryDiscipline.d.ts +3 -3
  156. package/dist/src/programmes/policies/DegreeCountryDiscipline.js +6 -6
  157. package/dist/src/programmes/policies/DegreeCountryTuitionFee.d.ts +3 -3
  158. package/dist/src/programmes/policies/DegreeCountryTuitionFee.js +6 -6
  159. package/dist/src/programmes/policies/DegreeDuration.d.ts +2 -2
  160. package/dist/src/programmes/policies/DegreeDuration.js +5 -5
  161. package/dist/src/programmes/policies/DegreeFormat.d.ts +2 -2
  162. package/dist/src/programmes/policies/DegreeFormat.js +5 -5
  163. package/dist/src/programmes/policies/DegreeSpecialProgrammes.d.ts +3 -3
  164. package/dist/src/programmes/policies/DegreeSpecialProgrammes.js +5 -5
  165. package/dist/src/programmes/policies/DegreeTuitionFee.d.ts +3 -3
  166. package/dist/src/programmes/policies/DegreeTuitionFee.js +5 -5
  167. package/dist/src/programmes/policies/{DisciplineTuitionFee.d.ts → DegreeTuitionFeeArea.d.ts} +5 -5
  168. package/dist/src/programmes/policies/{DegreeAreaTuitionFee.js → DegreeTuitionFeeArea.js} +7 -7
  169. package/dist/src/programmes/policies/{DegreeAttendanceTuitionFee.d.ts → DegreeTuitionFeeAttendance.d.ts} +2 -2
  170. package/dist/src/programmes/policies/{DegreeAttendanceTuitionFee.js → DegreeTuitionFeeAttendance.js} +7 -7
  171. package/dist/src/programmes/policies/{DegreeContinentTuitionFee.d.ts → DegreeTuitionFeeContinent.d.ts} +2 -2
  172. package/dist/src/programmes/policies/{DegreeContinentTuitionFee.js → DegreeTuitionFeeContinent.js} +6 -6
  173. package/dist/src/programmes/policies/{DegreeFormatTuitionFee.d.ts → DegreeTuitionFeeFormat.d.ts} +3 -3
  174. package/dist/src/programmes/policies/{DegreeFormatTuitionFee.js → DegreeTuitionFeeFormat.js} +9 -9
  175. package/dist/src/programmes/policies/Discipline.d.ts +3 -3
  176. package/dist/src/programmes/policies/Discipline.js +4 -4
  177. package/dist/src/programmes/policies/DisciplineAttendance.d.ts +4 -4
  178. package/dist/src/programmes/policies/DisciplineAttendance.js +6 -6
  179. package/dist/src/programmes/policies/DisciplineContinent.d.ts +3 -3
  180. package/dist/src/programmes/policies/DisciplineContinent.js +5 -5
  181. package/dist/src/programmes/policies/DisciplineContinentAttendance.d.ts +4 -4
  182. package/dist/src/programmes/policies/DisciplineContinentAttendance.js +7 -7
  183. package/dist/src/programmes/policies/DisciplineCountry.d.ts +3 -3
  184. package/dist/src/programmes/policies/DisciplineCountry.js +5 -5
  185. package/dist/src/programmes/policies/DisciplineCountryAttendance.d.ts +4 -4
  186. package/dist/src/programmes/policies/DisciplineCountryAttendance.js +7 -7
  187. package/dist/src/programmes/policies/DisciplineCountryEducationalForm.d.ts +2 -2
  188. package/dist/src/programmes/policies/DisciplineCountryEducationalForm.js +6 -6
  189. package/dist/src/programmes/policies/DisciplineCountryFormat.d.ts +3 -3
  190. package/dist/src/programmes/policies/DisciplineCountryFormat.js +6 -6
  191. package/dist/src/programmes/policies/DisciplineDegree.d.ts +3 -3
  192. package/dist/src/programmes/policies/DisciplineDegree.js +5 -5
  193. package/dist/src/programmes/policies/DisciplineDuration.d.ts +3 -3
  194. package/dist/src/programmes/policies/DisciplineDuration.js +5 -5
  195. package/dist/src/programmes/policies/DisciplineEducationalForm.d.ts +2 -2
  196. package/dist/src/programmes/policies/DisciplineEducationalForm.js +5 -5
  197. package/dist/src/programmes/policies/DisciplineFormat.d.ts +3 -3
  198. package/dist/src/programmes/policies/DisciplineFormat.js +5 -5
  199. package/dist/src/programmes/policies/DisciplineSpecialProgrammes.d.ts +3 -3
  200. package/dist/src/programmes/policies/DisciplineSpecialProgrammes.js +5 -5
  201. package/dist/src/programmes/policies/Duration.d.ts +3 -3
  202. package/dist/src/programmes/policies/Duration.js +4 -4
  203. package/dist/src/programmes/policies/Format.d.ts +3 -3
  204. package/dist/src/programmes/policies/Format.js +4 -4
  205. package/dist/src/programmes/policies/SpecialProgrammes.d.ts +3 -3
  206. package/dist/src/programmes/policies/SpecialProgrammes.js +4 -4
  207. package/dist/src/programmes/policies/TuitionFee.d.ts +3 -3
  208. package/dist/src/programmes/policies/TuitionFee.js +4 -4
  209. package/dist/src/programmes/policies/TuitionFeeAttendance.d.ts +4 -4
  210. package/dist/src/programmes/policies/TuitionFeeAttendance.js +6 -6
  211. package/dist/src/programmes/policies/TuitionFeeAttendanceDiscipline.d.ts +4 -4
  212. package/dist/src/programmes/policies/TuitionFeeAttendanceDiscipline.js +7 -7
  213. package/dist/src/programmes/policies/TuitionFeeContinent.d.ts +3 -3
  214. package/dist/src/programmes/policies/TuitionFeeContinent.js +5 -5
  215. package/dist/src/programmes/policies/TuitionFeeCountry.d.ts +3 -3
  216. package/dist/src/programmes/policies/TuitionFeeCountry.js +5 -5
  217. package/dist/src/programmes/policies/TuitionFeeDiscipline.d.ts +3 -3
  218. package/dist/src/programmes/policies/TuitionFeeDiscipline.js +5 -5
  219. package/dist/src/programmes/policies/Unfiltered.d.ts +2 -2
  220. package/dist/src/programmes/policies/Unfiltered.js +2 -2
  221. package/dist/src/programmes/policies/index.d.ts +4 -5
  222. package/dist/src/programmes/policies/index.js +4 -5
  223. package/dist/src/programmes/rules/DegreeAttendanceDisciplineRule.d.ts +2 -2
  224. package/dist/src/programmes/rules/DegreeAttendanceDisciplineSpecificRule.d.ts +2 -2
  225. package/dist/src/programmes/rules/DegreeCountryAttendanceSpecificRule.d.ts +2 -2
  226. package/dist/src/programmes/rules/DegreeCountryDisciplineSpecificRule.d.ts +2 -2
  227. package/dist/src/programmes/rules/DegreeCountryTuitionFeeSpecificRule.d.ts +2 -2
  228. package/dist/src/programmes/rules/DegreeDisciplineRule.d.ts +2 -2
  229. package/dist/src/programmes/rules/IndexableDegreeRule.d.ts +2 -2
  230. package/dist/src/programmes/rules/IndexableDegreeRule.js +1 -1
  231. package/dist/src/programmes/rules/IndexableDurationRule.d.ts +2 -2
  232. package/dist/src/programmes/rules/IndexableDurationRule.js +1 -1
  233. package/dist/src/programmes/rules/IndexableEducationalFormRule.d.ts +2 -2
  234. package/dist/src/programmes/rules/IndexableEducationalFormRule.js +1 -1
  235. package/dist/src/programmes/rules/IndexablePageNumberRule.js +1 -1
  236. package/dist/src/programmes/rules/MbaOrMscDegreeRule.d.ts +2 -2
  237. package/dist/src/programmes/rules/MinimumAmountOfResultsRule.d.ts +3 -3
  238. package/dist/src/programmes/rules/MinimumAmountOfResultsRule.js +1 -1
  239. package/dist/src/programmes/rules/NotDistanceLearningPortalRule.js +1 -1
  240. package/dist/src/programmes/rules/OneYearOnlyRule.d.ts +2 -2
  241. package/dist/src/programmes/types/IProgrammeSearchApplicationState.d.ts +1 -1
  242. package/dist/src/programmes/types/IProgrammeSearchDependencies.d.ts +1 -1
  243. package/dist/src/programmes/types/IProgrammeSearchSitemapDependencies.d.ts +1 -1
  244. package/dist/src/programmes/types/IProgrammeSitemapDependencies.d.ts +2 -2
  245. package/dist/src/programmes/types/IProgrammeSitemapUrlGenerator.d.ts +1 -1
  246. package/dist/src/scholarships/SearchIndexabilityManager.d.ts +5 -5
  247. package/dist/src/scholarships/SearchIndexabilityManager.js +1 -1
  248. package/dist/src/scholarships/policies/Area.d.ts +3 -3
  249. package/dist/src/scholarships/policies/Area.js +4 -4
  250. package/dist/src/scholarships/policies/Country.d.ts +3 -3
  251. package/dist/src/scholarships/policies/Country.js +4 -4
  252. package/dist/src/scholarships/policies/Discipline.d.ts +4 -4
  253. package/dist/src/scholarships/policies/Discipline.js +5 -5
  254. package/dist/src/scholarships/policies/DisciplineCountry.d.ts +3 -3
  255. package/dist/src/scholarships/policies/DisciplineCountry.js +5 -5
  256. package/dist/src/scholarships/policies/ScholarshipSeoIndexabilityPolicy.d.ts +2 -2
  257. package/dist/src/scholarships/policies/ScholarshipSeoIndexabilityPolicy.js +2 -2
  258. package/dist/src/scholarships/policies/Unfiltered.d.ts +2 -2
  259. package/dist/src/scholarships/policies/Unfiltered.js +2 -2
  260. package/dist/src/scholarships/policies/UniversityCountry.d.ts +3 -3
  261. package/dist/src/scholarships/policies/UniversityCountry.js +4 -4
  262. package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.d.ts +3 -3
  263. package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.js +1 -1
  264. package/dist/src/scholarships/rules/SearchVolumeAreasRule.d.ts +3 -3
  265. package/dist/src/scholarships/rules/SearchVolumeCountriesDisciplinesRule.d.ts +3 -3
  266. package/dist/src/scholarships/rules/SearchVolumeCountriesRule.d.ts +3 -3
  267. package/dist/src/scholarships/rules/SearchVolumeDisciplinesRule.d.ts +3 -3
  268. package/dist/src/scholarships/types/IScholarshipSeoDependencies.d.ts +1 -1
  269. package/dist/src/scholarships/types/IScholarshipSitemapDependencies.d.ts +2 -2
  270. package/dist/src/sitemap-generator/BaseSitemapUrlGeneratorManager.d.ts +3 -3
  271. package/dist/src/sitemap-generator/IRankingApiClient.d.ts +1 -1
  272. package/dist/src/sitemap-generator/ISearchApiClient.d.ts +1 -1
  273. package/dist/src/sitemap-generator/ISitemapUrlGeneratorManager.d.ts +3 -3
  274. package/dist/src/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.d.ts +4 -4
  275. package/dist/src/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.js +8 -8
  276. package/dist/src/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.d.ts +3 -3
  277. package/dist/src/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.js +15 -15
  278. package/dist/src/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.d.ts +3 -3
  279. package/dist/src/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.js +7 -7
  280. package/dist/src/structured-data/OrganisationStructuredDataFactory.d.ts +1 -1
  281. package/dist/src/structured-data/ProgrammeStructuredDataFactory.d.ts +1 -1
  282. package/dist/tests/common/rules/NoFiltersSelectedRule.test.d.mts +1 -0
  283. package/dist/tests/common/rules/NoFiltersSelectedRule.test.mjs +40 -0
  284. package/dist/tests/common/rules/OnlyFiltersSelectedRule.test.d.mts +1 -0
  285. package/dist/tests/common/rules/OnlyFiltersSelectedRule.test.mjs +70 -0
  286. package/dist/tests/common/rules/SingleValueSelectedForFilterRule.test.d.mts +1 -0
  287. package/dist/tests/common/rules/SingleValueSelectedForFilterRule.test.mjs +54 -0
  288. package/dist/tests/organisations/policies/our-picks/Area.test.d.mts +1 -0
  289. package/dist/tests/organisations/policies/our-picks/Area.test.mjs +125 -0
  290. package/dist/tests/organisations/policies/our-picks/AreaAttendance.test.d.mts +1 -0
  291. package/dist/tests/organisations/policies/our-picks/AreaAttendance.test.mjs +238 -0
  292. package/dist/tests/organisations/policies/our-picks/Attendance.test.d.mts +1 -0
  293. package/dist/tests/organisations/policies/our-picks/Attendance.test.mjs +119 -0
  294. package/dist/tests/organisations/policies/our-picks/Continent.test.d.mts +1 -0
  295. package/dist/tests/organisations/policies/our-picks/Continent.test.mjs +105 -0
  296. package/dist/tests/organisations/policies/our-picks/Country.test.d.mts +1 -0
  297. package/dist/tests/organisations/policies/our-picks/Country.test.mjs +109 -0
  298. package/dist/tests/organisations/policies/our-picks/CountryAreaCity.test.d.mts +1 -0
  299. package/dist/tests/organisations/policies/our-picks/CountryAreaCity.test.mjs +152 -0
  300. package/dist/tests/organisations/policies/our-picks/CountryAttendance.test.d.mts +1 -0
  301. package/dist/tests/organisations/policies/our-picks/CountryAttendance.test.mjs +223 -0
  302. package/dist/tests/organisations/policies/our-picks/CountryCity.test.d.mts +1 -0
  303. package/dist/tests/organisations/policies/our-picks/CountryCity.test.mjs +109 -0
  304. package/dist/tests/organisations/policies/our-picks/Unfiltered.test.d.mts +1 -0
  305. package/dist/tests/organisations/policies/our-picks/Unfiltered.test.mjs +60 -0
  306. package/dist/tests/organisations/policies/ranked/RankedArea.test.d.mts +1 -0
  307. package/dist/tests/organisations/policies/ranked/RankedArea.test.mjs +149 -0
  308. package/dist/tests/organisations/policies/ranked/RankedAreaDiscipline.test.d.mts +1 -0
  309. package/dist/tests/organisations/policies/ranked/RankedAreaDiscipline.test.mjs +237 -0
  310. package/dist/tests/organisations/policies/ranked/RankedAttendance.test.d.mts +1 -0
  311. package/dist/tests/organisations/policies/ranked/RankedAttendance.test.mjs +139 -0
  312. package/dist/tests/organisations/policies/ranked/RankedAttendanceDiscipline.test.d.mts +1 -0
  313. package/dist/tests/organisations/policies/ranked/RankedAttendanceDiscipline.test.mjs +224 -0
  314. package/dist/tests/organisations/policies/ranked/RankedContinent.test.d.mts +1 -0
  315. package/dist/tests/organisations/policies/ranked/RankedContinent.test.mjs +125 -0
  316. package/dist/tests/organisations/policies/ranked/RankedContinentAttendance.test.d.mts +1 -0
  317. package/dist/tests/organisations/policies/ranked/RankedContinentAttendance.test.mjs +253 -0
  318. package/dist/tests/organisations/policies/ranked/RankedCountry.test.d.mts +1 -0
  319. package/dist/tests/organisations/policies/ranked/RankedCountry.test.mjs +131 -0
  320. package/dist/tests/organisations/policies/ranked/RankedCountryAttendance.test.d.mts +1 -0
  321. package/dist/tests/organisations/policies/ranked/RankedCountryAttendance.test.mjs +230 -0
  322. package/dist/tests/organisations/policies/ranked/RankedCountryDiscipline.test.d.mts +1 -0
  323. package/dist/tests/organisations/policies/ranked/RankedCountryDiscipline.test.mjs +197 -0
  324. package/dist/tests/organisations/policies/ranked/RankedDiscipline.test.d.mts +1 -0
  325. package/dist/tests/organisations/policies/ranked/RankedDiscipline.test.mjs +124 -0
  326. package/dist/tests/organisations/policies/ranked/RankedUnfiltered.test.d.mts +1 -0
  327. package/dist/tests/organisations/policies/ranked/RankedUnfiltered.test.mjs +75 -0
  328. package/dist/tests/organisations/rules/ContinentIsEuropeRule.test.d.mts +1 -0
  329. package/dist/tests/organisations/rules/ContinentIsEuropeRule.test.mjs +59 -0
  330. package/dist/tests/organisations/rules/MinimumAmountOfRankedResultsRule.test.d.mts +1 -0
  331. package/dist/tests/organisations/rules/MinimumAmountOfRankedResultsRule.test.mjs +77 -0
  332. package/dist/tests/organisations/rules/MinimumAmountOfResultsRule.test.d.mts +1 -0
  333. package/dist/tests/organisations/rules/MinimumAmountOfResultsRule.test.mjs +77 -0
  334. package/dist/tests/organisations/rules/OnlineAttendanceRule.test.d.mts +1 -0
  335. package/dist/tests/organisations/rules/OnlineAttendanceRule.test.mjs +59 -0
  336. package/dist/tests/organisations/rules/SearchVolumeAreasAttendanceRule.test.d.mts +1 -0
  337. package/dist/tests/organisations/rules/SearchVolumeAreasAttendanceRule.test.mjs +59 -0
  338. package/dist/tests/organisations/rules/SearchVolumeAreasDisciplineRule.test.d.mts +1 -0
  339. package/dist/tests/organisations/rules/SearchVolumeAreasDisciplineRule.test.mjs +59 -0
  340. package/dist/tests/organisations/rules/SearchVolumeCountriesAttendanceRule.test.d.mts +1 -0
  341. package/dist/tests/organisations/rules/SearchVolumeCountriesAttendanceRule.test.mjs +59 -0
  342. package/dist/tests/organisations/utils/SearchDependencies.util.d.mts +20 -0
  343. package/dist/tests/organisations/utils/SearchDependencies.util.mjs +88 -0
  344. package/dist/tests/organisations/utils/SitemapDependencies.util.d.mts +18 -0
  345. package/dist/tests/organisations/utils/SitemapDependencies.util.mjs +54 -0
  346. package/dist/tests/presenters/AreaPresenter.test.d.mts +1 -0
  347. package/dist/tests/presenters/AreaPresenter.test.mjs +46 -0
  348. package/dist/tests/presenters/AttendancePresenter.test.d.mts +1 -0
  349. package/dist/tests/presenters/AttendancePresenter.test.mjs +41 -0
  350. package/dist/tests/presenters/ContinentPresenter.test.d.mts +1 -0
  351. package/dist/tests/presenters/ContinentPresenter.test.mjs +44 -0
  352. package/dist/tests/presenters/CountryPresenter.test.d.mts +1 -0
  353. package/dist/tests/presenters/CountryPresenter.test.mjs +50 -0
  354. package/dist/tests/presenters/DegreePresenter.test.d.mts +1 -0
  355. package/dist/tests/presenters/DegreePresenter.test.mjs +51 -0
  356. package/dist/tests/presenters/DisciplinePresenter.test.d.mts +1 -0
  357. package/dist/tests/presenters/DisciplinePresenter.test.mjs +40 -0
  358. package/dist/tests/presenters/DurationPresenter.test.d.mts +1 -0
  359. package/dist/tests/presenters/DurationPresenter.test.mjs +64 -0
  360. package/dist/tests/presenters/EducationalFormPresenter.test.d.mts +1 -0
  361. package/dist/tests/presenters/EducationalFormPresenter.test.mjs +60 -0
  362. package/dist/tests/presenters/FormatPresenter.test.d.mts +1 -0
  363. package/dist/tests/presenters/FormatPresenter.test.mjs +43 -0
  364. package/dist/tests/presenters/SpecialProgrammesPresenter.test.d.mts +1 -0
  365. package/dist/tests/presenters/SpecialProgrammesPresenter.test.mjs +66 -0
  366. package/dist/tests/presenters/TuitionFeePresenter.test.d.mts +1 -0
  367. package/dist/tests/presenters/TuitionFeePresenter.test.mjs +52 -0
  368. package/dist/tests/programmes/policies/Area.test.d.mts +1 -0
  369. package/dist/tests/programmes/policies/Area.test.mjs +153 -0
  370. package/dist/tests/programmes/policies/Attendance.test.d.mts +1 -0
  371. package/dist/tests/programmes/policies/Attendance.test.mjs +173 -0
  372. package/dist/tests/programmes/policies/AttendanceDegree.test.d.mts +1 -0
  373. package/dist/tests/programmes/policies/AttendanceDegree.test.mjs +291 -0
  374. package/dist/tests/programmes/policies/Continent.test.d.mts +1 -0
  375. package/dist/tests/programmes/policies/Continent.test.mjs +169 -0
  376. package/dist/tests/programmes/policies/Country.test.d.mts +1 -0
  377. package/dist/tests/programmes/policies/Country.test.mjs +164 -0
  378. package/dist/tests/programmes/policies/CountryAttendance.test.d.mts +1 -0
  379. package/dist/tests/programmes/policies/CountryAttendance.test.mjs +251 -0
  380. package/dist/tests/programmes/policies/CountryAttendanceDegree.test.d.mts +1 -0
  381. package/dist/tests/programmes/policies/CountryAttendanceDegree.test.mjs +337 -0
  382. package/dist/tests/programmes/policies/CountryDegree.test.d.mts +1 -0
  383. package/dist/tests/programmes/policies/CountryDegree.test.mjs +262 -0
  384. package/dist/tests/programmes/policies/CountryDuration.test.d.mts +1 -0
  385. package/dist/tests/programmes/policies/CountryDuration.test.mjs +234 -0
  386. package/dist/tests/programmes/policies/CountryDurationDegree.test.d.mts +1 -0
  387. package/dist/tests/programmes/policies/CountryDurationDegree.test.mjs +304 -0
  388. package/dist/tests/programmes/policies/CountryEducationalForm.test.d.mts +1 -0
  389. package/dist/tests/programmes/policies/CountryEducationalForm.test.mjs +260 -0
  390. package/dist/tests/programmes/policies/CountryFormat.test.d.mts +1 -0
  391. package/dist/tests/programmes/policies/CountryFormat.test.mjs +253 -0
  392. package/dist/tests/programmes/policies/DegreeAttendanceDiscipline.test.d.mts +1 -0
  393. package/dist/tests/programmes/policies/DegreeAttendanceDiscipline.test.mjs +179 -0
  394. package/dist/tests/programmes/policies/DegreeCountryAttendance.test.d.mts +1 -0
  395. package/dist/tests/programmes/policies/DegreeCountryAttendance.test.mjs +267 -0
  396. package/dist/tests/programmes/policies/DegreeCountryTuitionFee.test.d.mts +1 -0
  397. package/dist/tests/programmes/policies/DegreeCountryTuitionFee.test.mjs +217 -0
  398. package/dist/tests/programmes/policies/DegreeFormat.test.d.mts +1 -0
  399. package/dist/tests/programmes/policies/DegreeFormat.test.mjs +221 -0
  400. package/dist/tests/programmes/policies/Discipline.test.d.mts +1 -0
  401. package/dist/tests/programmes/policies/Discipline.test.mjs +159 -0
  402. package/dist/tests/programmes/policies/DisciplineAttendance.test.d.mts +1 -0
  403. package/dist/tests/programmes/policies/DisciplineAttendance.test.mjs +292 -0
  404. package/dist/tests/programmes/policies/DisciplineContinent.test.d.mts +1 -0
  405. package/dist/tests/programmes/policies/DisciplineContinent.test.mjs +253 -0
  406. package/dist/tests/programmes/policies/DisciplineCountry.test.d.mts +1 -0
  407. package/dist/tests/programmes/policies/DisciplineCountry.test.mjs +244 -0
  408. package/dist/tests/programmes/policies/DisciplineCountryEducationalForm.test.d.mts +1 -0
  409. package/dist/tests/programmes/policies/DisciplineCountryEducationalForm.test.mjs +345 -0
  410. package/dist/tests/programmes/policies/DisciplineDegree.test.d.mts +1 -0
  411. package/dist/tests/programmes/policies/DisciplineDegree.test.mjs +273 -0
  412. package/dist/tests/programmes/policies/DisciplineDuration.test.d.mts +1 -0
  413. package/dist/tests/programmes/policies/DisciplineDuration.test.mjs +278 -0
  414. package/dist/tests/programmes/policies/DisciplineEducationalForm.test.d.mts +1 -0
  415. package/dist/tests/programmes/policies/DisciplineEducationalForm.test.mjs +302 -0
  416. package/dist/tests/programmes/policies/DisciplineFormat.test.d.mts +1 -0
  417. package/dist/tests/programmes/policies/DisciplineFormat.test.mjs +266 -0
  418. package/dist/tests/programmes/policies/Duration.test.d.mts +1 -0
  419. package/dist/tests/programmes/policies/Duration.test.mjs +179 -0
  420. package/dist/tests/programmes/policies/Format.test.d.mts +1 -0
  421. package/dist/tests/programmes/policies/Format.test.mjs +117 -0
  422. package/dist/tests/programmes/policies/NewRulesValidation.test.d.mts +1 -0
  423. package/dist/tests/programmes/policies/NewRulesValidation.test.mjs +320 -0
  424. package/dist/tests/programmes/policies/SpecialProgrammes.test.d.mts +1 -0
  425. package/dist/tests/programmes/policies/SpecialProgrammes.test.mjs +171 -0
  426. package/dist/tests/programmes/policies/TuitionFeeAttendanceDiscipline.test.d.mts +1 -0
  427. package/dist/tests/programmes/policies/TuitionFeeAttendanceDiscipline.test.mjs +360 -0
  428. package/dist/tests/programmes/policies/TuitionFeeContinent.test.d.mts +1 -0
  429. package/dist/tests/programmes/policies/TuitionFeeContinent.test.mjs +293 -0
  430. package/dist/tests/programmes/policies/TuitionFeeCountry.test.d.mts +1 -0
  431. package/dist/tests/programmes/policies/TuitionFeeCountry.test.mjs +266 -0
  432. package/dist/tests/programmes/policies/TuitionFeeDiscipline.test.d.mts +1 -0
  433. package/dist/tests/programmes/policies/TuitionFeeDiscipline.test.mjs +267 -0
  434. package/dist/tests/programmes/policies/Unfiltered.test.d.mts +1 -0
  435. package/dist/tests/programmes/policies/Unfiltered.test.mjs +90 -0
  436. package/dist/tests/programmes/rules/AffordableTuitionFeeRule.test.d.mts +1 -0
  437. package/dist/tests/programmes/rules/AffordableTuitionFeeRule.test.mjs +27 -0
  438. package/dist/tests/programmes/rules/DegreeCountrySpecificRule.test.d.mts +1 -0
  439. package/dist/tests/programmes/rules/DegreeCountrySpecificRule.test.mjs +121 -0
  440. package/dist/tests/programmes/rules/DegreeDisciplineRule.test.d.mts +1 -0
  441. package/dist/tests/programmes/rules/DegreeDisciplineRule.test.mjs +169 -0
  442. package/dist/tests/programmes/rules/IndexableDegreeRule.test.d.mts +1 -0
  443. package/dist/tests/programmes/rules/IndexableDegreeRule.test.mjs +101 -0
  444. package/dist/tests/programmes/rules/IndexableDurationRule.test..d.mts +1 -0
  445. package/dist/tests/programmes/rules/IndexableDurationRule.test..mjs +25 -0
  446. package/dist/tests/programmes/rules/IndexableEducationalFormRule.test.d.mts +1 -0
  447. package/dist/tests/programmes/rules/IndexableEducationalFormRule.test.mjs +27 -0
  448. package/dist/tests/programmes/rules/IndexablePageNumberRule.test.d.mts +1 -0
  449. package/dist/tests/programmes/rules/IndexablePageNumberRule.test.mjs +51 -0
  450. package/dist/tests/programmes/rules/MbaDegreeRule.test.d.mts +1 -0
  451. package/dist/tests/programmes/rules/MbaDegreeRule.test.mjs +55 -0
  452. package/dist/tests/programmes/rules/MbaOrMscDegreeRule.test.d.mts +1 -0
  453. package/dist/tests/programmes/rules/MbaOrMscDegreeRule.test.mjs +53 -0
  454. package/dist/tests/programmes/rules/MinimumAmountOfResultsRule.test.d.mts +1 -0
  455. package/dist/tests/programmes/rules/MinimumAmountOfResultsRule.test.mjs +79 -0
  456. package/dist/tests/programmes/rules/NotDistanceLearningPortalRule.test.d.mts +1 -0
  457. package/dist/tests/programmes/rules/NotDistanceLearningPortalRule.test.mjs +57 -0
  458. package/dist/tests/programmes/rules/OneYearDurationRule.test..d.mts +1 -0
  459. package/dist/tests/programmes/rules/OneYearDurationRule.test..mjs +40 -0
  460. package/dist/tests/programmes/rules/OnlineAttendanceRule.test.d.mts +1 -0
  461. package/dist/tests/programmes/rules/OnlineAttendanceRule.test.mjs +69 -0
  462. package/dist/tests/programmes/rules/PartTimeFormatRule.test.d.mts +1 -0
  463. package/dist/tests/programmes/rules/PartTimeFormatRule.test.mjs +27 -0
  464. package/dist/tests/programmes/utils/SearchDependencies.util.d.mts +16 -0
  465. package/dist/tests/programmes/utils/SearchDependencies.util.mjs +73 -0
  466. package/dist/tests/programmes/utils/SitemapDependencies.util.d.mts +15 -0
  467. package/dist/tests/programmes/utils/SitemapDependencies.util.mjs +49 -0
  468. package/dist/tests/scholarships/policies/Area.test.d.mts +1 -0
  469. package/dist/tests/scholarships/policies/Area.test.mjs +121 -0
  470. package/dist/tests/scholarships/policies/Country.test.d.mts +1 -0
  471. package/dist/tests/scholarships/policies/Country.test.mjs +97 -0
  472. package/dist/tests/scholarships/policies/Discipline.test.d.mts +1 -0
  473. package/dist/tests/scholarships/policies/Discipline.test.mjs +93 -0
  474. package/dist/tests/scholarships/policies/DisciplineCountry.test.d.mts +1 -0
  475. package/dist/tests/scholarships/policies/DisciplineCountry.test.mjs +151 -0
  476. package/dist/tests/scholarships/policies/Unfiltered.test.d.mts +1 -0
  477. package/dist/tests/scholarships/policies/Unfiltered.test.mjs +44 -0
  478. package/dist/tests/scholarships/policies/UniversityCountry.test.d.mts +1 -0
  479. package/dist/tests/scholarships/policies/UniversityCountry.test.mjs +115 -0
  480. package/dist/tests/scholarships/rules/ExceptAustaliaAreasRule.test.d.mts +1 -0
  481. package/dist/tests/scholarships/rules/ExceptAustaliaAreasRule.test.mjs +64 -0
  482. package/dist/tests/scholarships/rules/SearchVolumeAreasRule.test.d.mts +1 -0
  483. package/dist/tests/scholarships/rules/SearchVolumeAreasRule.test.mjs +62 -0
  484. package/dist/tests/scholarships/rules/SearchVolumeCountriesDisciplinesRule.test.d.mts +1 -0
  485. package/dist/tests/scholarships/rules/SearchVolumeCountriesDisciplinesRule.test.mjs +114 -0
  486. package/dist/tests/scholarships/rules/SearchVolumeCountriesRule.test.d.mts +1 -0
  487. package/dist/tests/scholarships/rules/SearchVolumeCountriesRule.test.mjs +62 -0
  488. package/dist/tests/scholarships/rules/SearchVolumeDisciplinesRule.test.d.mts +1 -0
  489. package/dist/tests/scholarships/rules/SearchVolumeDisciplinesRule.test.mjs +62 -0
  490. package/dist/tests/scholarships/utils/SearchDependencies.util.d.mts +16 -0
  491. package/dist/tests/scholarships/utils/SearchDependencies.util.mjs +70 -0
  492. package/dist/tests/scholarships/utils/SitemapDependencies.util.d.mts +11 -0
  493. package/dist/tests/scholarships/utils/SitemapDependencies.util.mjs +33 -0
  494. package/dist/tests/sitemap-generator/BaseSitemapUrlGeneratorManager.test.d.mts +1 -0
  495. package/dist/tests/sitemap-generator/BaseSitemapUrlGeneratorManager.test.mjs +82 -0
  496. package/dist/tests/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.test.d.mts +1 -0
  497. package/dist/tests/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.test.mjs +85 -0
  498. package/dist/tests/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.test.d.mts +1 -0
  499. package/dist/tests/sitemap-generator/ProgrammesSitemapUrlGeneratorManager.test.mjs +77 -0
  500. package/dist/tests/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.test.d.mts +1 -0
  501. package/dist/tests/sitemap-generator/ScholarshipsSitemapUrlGeneratorManager.test.mjs +60 -0
  502. package/dist/tests/structured-data/OrganisationStructuredDataFactory.test.d.mts +1 -0
  503. package/dist/tests/structured-data/OrganisationStructuredDataFactory.test.mjs +334 -0
  504. package/dist/tests/structured-data/ProgrammeStructuredDataFactory.test.d.mts +1 -0
  505. package/dist/tests/structured-data/ProgrammeStructuredDataFactory.test.mjs +562 -0
  506. package/dist/tests/structured-data/ScholarshipStructuredDataFactory.test.d.mts +1 -0
  507. package/dist/tests/structured-data/ScholarshipStructuredDataFactory.test.mjs +292 -0
  508. package/dist/tests/structured-data/SearchStructuredDataFactory.paywall.test.d.mts +1 -0
  509. package/dist/tests/structured-data/SearchStructuredDataFactory.paywall.test.mjs +258 -0
  510. package/package.json +1 -1
  511. package/dist/src/programmes/policies/AttendanceTuitionFee.d.ts +0 -17
  512. package/dist/src/programmes/policies/AttendanceTuitionFee.js +0 -51
  513. package/dist/src/programmes/policies/ContinentTuitionFee.d.ts +0 -16
  514. package/dist/src/programmes/policies/ContinentTuitionFee.js +0 -46
  515. package/dist/src/programmes/policies/CountryTuitionFee.d.ts +0 -16
  516. package/dist/src/programmes/policies/CountryTuitionFee.js +0 -46
  517. package/dist/src/programmes/policies/DegreeAreaTuitionFee.d.ts +0 -16
  518. package/dist/src/programmes/policies/DisciplineTuitionFee.js +0 -46
  519. package/dist/src/programmes/policies/DisciplineTuitionFeeAttendance.d.ts +0 -17
  520. 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
+ });