JobsUnifiedTopCard.purs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. module Test.JobsUnifiedTopCard where
  2. import Prelude
  3. import Data.Either (Either(..))
  4. import Data.List (List(..), (:))
  5. import Data.List.NonEmpty (NonEmptyList(..))
  6. import Data.List.NonEmpty as NEL
  7. import Data.Maybe (Maybe(..), isJust)
  8. import Data.NonEmpty (NonEmpty(..))
  9. import Data.Traversable (traverse)
  10. import Effect (Effect)
  11. import LinkedIn (LinkedInUIElement(..), getJobsUnifiedTopCard)
  12. import LinkedIn.DetachedNode (DetachedNode(..), toDetached)
  13. import LinkedIn.JobsUnifiedTopCard (JobsUnifiedTopCardElement(..), TopCardAction(..), TopCardInsight(..), TopCardInsightContent(..), TopCardPrimaryDescription(..), TopCardSecondaryInsight(..), queryJobsUnifiedTopCardElement)
  14. import LinkedIn.QueryRunner (QueryError, runQuery)
  15. import Node.JsDom (jsDomFromFile)
  16. import Partial.Unsafe (unsafePartial)
  17. import Test.Assert (assert, assertEqual)
  18. testJobsUnifiedTopCard :: Effect Unit
  19. testJobsUnifiedTopCard = do
  20. dom <- jsDomFromFile "test/examples/job_offer.html"
  21. topCard <- getJobsUnifiedTopCard dom
  22. assert $ isJust topCard
  23. headCard <- unsafePartial $ parseHeadCard topCard
  24. assertEqual {
  25. actual: headCard,
  26. expected: Right (JobsUnifiedTopCardElement {
  27. actions: (Just (NonEmptyList
  28. (NonEmpty (TopCardActionApplyButton (DetachedButton {
  29. classes: ("jobs-apply-button" : "artdeco-button" : "artdeco-button--3" : "artdeco-button--primary" : "ember-view" : Nil),
  30. content: "Candidature simplifiée",
  31. role: Nothing
  32. })) ((TopCardActionApplyButton (DetachedButton {
  33. classes: ("jobs-save-button" : "artdeco-button" : "artdeco-button--3" : "artdeco-button--secondary" : Nil),
  34. content: "Enregistrer Enregistrer Data Engineer H/F - Secteur Energie chez LINCOLN",
  35. role: Nothing
  36. })) : Nil)))),
  37. header: (DetachedElement {
  38. classes: ("t-24" : "t-bold" : "job-details-jobs-unified-top-card__job-title" : Nil),
  39. content: "Data Engineer H/F - Secteur Energie",
  40. id: Nothing,
  41. tag: "H1"
  42. }),
  43. insights: (Just (NonEmptyList
  44. (NonEmpty (TopCardInsight {
  45. content: (TopCardInsightContentSecondary {
  46. primary: (DetachedElement {
  47. classes: ("" : Nil),
  48. content: "Sur site",
  49. id: Nothing,
  50. tag: "SPAN"
  51. }),
  52. secondary: (NonEmptyList (NonEmpty (TopCardSecondaryInsightNested
  53. (DetachedElement {
  54. classes: ("" : Nil),
  55. content: "Temps plein",
  56. id: Nothing,
  57. tag: "SPAN"
  58. })) ((TopCardSecondaryInsightPlain
  59. (DetachedElement {
  60. classes: ("job-details-jobs-unified-top-card__job-insight-view-model-secondary" : Nil),
  61. content: "Confirmé",
  62. id: (Just "undefined"),
  63. tag: "SPAN"
  64. })) : Nil))) }),
  65. icon: DetachedLiIcon "job"
  66. }) ((TopCardInsight {
  67. content: (TopCardInsightContentSingle (DetachedElement {
  68. classes: ("" : Nil),
  69. content: "201-500 employés · Technologies et services de l’information",
  70. id: (Just "undefined"),
  71. tag: "SPAN" })),
  72. icon: DetachedLiIcon "company"
  73. }) : (TopCardInsight {
  74. content: (TopCardInsightContentSingle (DetachedElement {
  75. classes: ("" : Nil),
  76. content: "2 anciens élèves travaillent ici",
  77. id: (Just "undefined"),
  78. tag: "SPAN" })),
  79. icon: DetachedLiIcon "people"
  80. }) : (TopCardInsight {
  81. content: (TopCardInsightContentSingle (DetachedElement {
  82. classes: ("" : Nil),
  83. content: "Découvrez comment vous vous positionnez par rapport à 87 candidats. Essai Premium pour 0 EUR",
  84. id: (Just "undefined"),
  85. tag: "SPAN" })),
  86. icon: (DetachedSvgElement { dataTestIcon: (Just "lightbulb-medium"), id: Nothing, tag: "svg" })
  87. }) : (TopCardInsight {
  88. content: (TopCardInsightContentButton (DetachedButton {
  89. classes: ("job-details-jobs-unified-top-card__job-insight-text-button" : Nil),
  90. content: "9 compétences sur 11 correspondent à votre profil, vous pourriez bien convenir pour ce poste",
  91. role: Nothing
  92. })),
  93. icon: (DetachedSvgElement { dataTestIcon: (Just "checklist-medium"), id: Nothing, tag: "svg" })
  94. }) : Nil)))),
  95. primaryDescription: (TopCardPrimaryDescription {
  96. link: (DetachedA { content: "LINCOLN", href: "https://www.linkedin.com/company/lincoln-/life" }),
  97. text: (DetachedText "· Boulogne-Billancourt, Île-de-France, France"),
  98. tvmText: (Just (NonEmptyList
  99. (NonEmpty (DetachedElement {
  100. classes: ("tvm__text" : "tvm__text--neutral" : Nil),
  101. content: "il y a 2 semaines",
  102. id: Nothing,
  103. tag: "SPAN"
  104. }) ((DetachedElement {
  105. classes: ("tvm__text" : "tvm__text--neutral" : Nil),
  106. content: "·",
  107. id: Nothing,
  108. tag: "SPAN"
  109. }) : (DetachedElement {
  110. classes: ("tvm__text" : "tvm__text--neutral" : Nil),
  111. content: "87 candidats",
  112. id: Nothing,
  113. tag: "SPAN"
  114. }) : Nil
  115. ))
  116. ))
  117. })
  118. })
  119. }
  120. parseHeadCard ∷ Partial ⇒ Maybe (NonEmptyList LinkedInUIElement) → Effect (Either QueryError (JobsUnifiedTopCardElement DetachedNode))
  121. parseHeadCard (Just l) = do
  122. queried <- (\(LinkedInUIElement _ n) -> runQuery $ queryJobsUnifiedTopCardElement n) $ NEL.head l
  123. case queried of
  124. Left l' -> pure $ Left l'
  125. Right q -> do
  126. parsed <- traverse toDetached q
  127. pure $ Right parsed