1
+ import { expect , test } from '@playwright/test' ;
2
+ import { TeachPage } from '../../page/teach/education' ;
3
+ import { closeExternalBanners } from '../utils' ;
4
+ import { testSelector } from '../../utils' ;
5
+ import { checkTeachCta , checkTeachMap , checkTeachSubnav , MAILTO_LINK , MATERIALS_LINK , SIGNUP_LINK } from './utils' ;
6
+
7
+ test . describe ( 'Education landing page content and interactions' , async ( ) => {
8
+ test . beforeEach ( async ( { context, page, baseURL } ) => {
9
+ const teachPage = new TeachPage ( page ) ;
10
+ await teachPage . init ( ) ;
11
+ await closeExternalBanners ( context , page , baseURL ) ;
12
+ } ) ;
13
+
14
+ test ( 'Should load the education page correctly' , async ( { page } ) => {
15
+ // Check if the page title is correct
16
+ expect ( await page . title ( ) ) . toBe ( 'Kotlin for Education' ) ;
17
+
18
+ // Check if the main content is visible
19
+ const mainContent = page . locator ( testSelector ( 'teach-index-page' ) ) ;
20
+ await expect ( mainContent ) . toBeVisible ( ) ;
21
+
22
+ // Check if the page heading is correct
23
+ const title = mainContent . locator ( 'h1' ) ;
24
+ await expect ( title ) . toBeVisible ( ) ;
25
+
26
+ expect ( await title . textContent ( ) ) . toBe ( 'Teach Computer Science with Kotlin' ) ;
27
+ } ) ;
28
+
29
+ test ( 'Should have working navigation buttons' , async ( { page } ) => {
30
+ await checkTeachSubnav ( page , 'Overview' ) ;
31
+ } ) ;
32
+
33
+ test ( 'Should display course materials download button' , async ( { page } ) => {
34
+ const block = page . locator ( '.teach-launch-course__text' ) ;
35
+
36
+ const button = block . locator ( `a[href="${ MATERIALS_LINK } "]` ) ;
37
+ await expect ( button ) . toBeVisible ( ) ;
38
+
39
+ expect ( await block . screenshot ( ) ) . toMatchSnapshot ( 'launch-course-text.png' ) ;
40
+ } ) ;
41
+
42
+ test ( 'Should display features section with features' , async ( { page } ) => {
43
+ // Check if the features section is visible
44
+ const featuresSection = page . locator ( '.teach-features' ) ;
45
+ await expect ( featuresSection ) . toBeVisible ( ) ;
46
+
47
+ // Check if there are exactly 3 features
48
+ const expectedFeatures = [ 'Academically recognized' , 'Language of the industry' , 'Multiplatform' ] ;
49
+ const features = featuresSection . locator ( '.teach-feature' ) ;
50
+ expect ( await features . count ( ) ) . toBe ( 3 ) ;
51
+
52
+ // Check each feature
53
+ for ( let i = 0 ; i < expectedFeatures . length ; i ++ ) {
54
+ const feature = features . nth ( i ) ;
55
+ await expect ( feature . locator ( '.teach-feature__icon img' ) ) . toBeVisible ( ) ;
56
+ expect ( await feature . locator ( '.ktl-h3' ) . textContent ( ) ) . toBe ( expectedFeatures [ i ] ) ;
57
+ }
58
+
59
+ expect ( await featuresSection . screenshot ( ) ) . toMatchSnapshot ( 'teach-features.png' ) ;
60
+ } ) ;
61
+
62
+ test ( 'Should display buttons in top section' , async ( { page } ) => {
63
+ const block = page . locator ( '.teach-top-buttons' ) ;
64
+
65
+ await expect ( block . locator ( `a[href="${ SIGNUP_LINK } "]` ) ) . toBeVisible ( ) ;
66
+ await expect ( block . locator ( `a[href="why-teach-kotlin.html"]` ) ) . toBeVisible ( ) ;
67
+
68
+ expect ( await block . screenshot ( ) ) . toMatchSnapshot ( 'teach-top-mobile-buttons.png' ) ;
69
+ } ) ;
70
+
71
+ test ( 'Should display university statistics correctly' , async ( { page } ) => {
72
+ // Check if the university count is displayed
73
+ const universitiesText = page . locator ( '.universities-top__title h2' ) ;
74
+ expect ( await universitiesText . textContent ( ) ) . toBe ( 'Kotlin Courses Around the World' ) ;
75
+
76
+ // Check if the TeachNumbers component is visible
77
+ const teachNumbers = page . locator ( '.universities-top__numbers' ) ;
78
+ await expect ( teachNumbers ) . toBeVisible ( ) ;
79
+
80
+ // Check if the TeachNumbers component is visible
81
+ const subtitles = teachNumbers . locator ( '.teach-number__subtitle' ) ;
82
+ expect ( await subtitles . count ( ) ) . toBe ( 2 ) ;
83
+ expect ( await subtitles . nth ( 0 ) . textContent ( ) ) . toBe ( 'countries' ) ;
84
+ expect ( await subtitles . nth ( 1 ) . textContent ( ) ) . toBe ( 'universities' ) ;
85
+ } ) ;
86
+
87
+ test ( 'Should display university logos' , async ( { page } ) => {
88
+ // Check if the university logos are visible
89
+ const logos = page . locator ( '.teach-logos__logo' ) ;
90
+ expect ( await logos . count ( ) ) . toBe ( 5 ) ;
91
+
92
+ // Check specific universities
93
+ await expect ( page . locator ( 'img[alt="Harvard University"]' ) ) . toBeVisible ( ) ;
94
+ await expect ( page . locator ( 'img[alt="University of Cambridge"]' ) ) . toBeVisible ( ) ;
95
+ await expect ( page . locator ( 'img[alt="Stanford University"]' ) ) . toBeVisible ( ) ;
96
+ await expect ( page . locator ( 'img[alt="Imperial College London"]' ) ) . toBeVisible ( ) ;
97
+ await expect ( page . locator ( 'img[alt="The University of Chicago"]' ) ) . toBeVisible ( ) ;
98
+
99
+ expect ( await page . locator ( '.teach-logos' ) . screenshot ( ) ) . toMatchSnapshot ( 'teach-logos.png' ) ;
100
+ } ) ;
101
+
102
+ test ( 'Should have a working interactive map' , async ( { page } ) => {
103
+ // Check if the map is visible
104
+ const map = page . locator ( '.teach-map__wrapper' ) ;
105
+ await checkTeachMap ( page , map ) ;
106
+ } ) ;
107
+
108
+ test ( 'Should display navigation buttons' , async ( { page } ) => {
109
+ const bottom = page . locator ( '.teach-universities__bottom' ) ;
110
+ await expect ( bottom ) . toBeVisible ( ) ;
111
+
112
+ // Check if the mailto button is visible and working
113
+ const mailtoButton = bottom . locator ( `a[href="${ MAILTO_LINK } "]` ) ;
114
+ await expect ( mailtoButton ) . toBeVisible ( ) ;
115
+
116
+ // Check if the "All Universities" button is visible
117
+ const allUniversitiesButton = bottom . locator ( 'a[href="courses.html"]' ) ;
118
+ await expect ( allUniversitiesButton ) . toBeVisible ( ) ;
119
+ } ) ;
120
+
121
+ test ( 'Should have comprehensive resource links section' , async ( { page } ) => {
122
+ // Check if the resources section is visible
123
+ const resourcesSection = page . locator ( '#start-teaching-kotlin' ) ;
124
+ await expect ( resourcesSection ) . toBeVisible ( ) ;
125
+
126
+ // Check section title
127
+ const sectionTitle = resourcesSection . locator ( 'h2' ) ;
128
+ await expect ( sectionTitle ) . toHaveText ( 'Start Teaching Kotlin with These Resources' ) ;
129
+
130
+ // Check category headings
131
+ const expectedTitles = [ 'Get started' , 'Tools' , 'Online Courses' , 'Android in Kotlin' , 'Practice Kotlin' ] ;
132
+ const categoryHeadings = resourcesSection . locator ( '.ktl-h4' ) ;
133
+ await expect ( categoryHeadings ) . toHaveCount ( expectedTitles . length ) ;
134
+
135
+ // Check each category heading and its associated links
136
+ for ( let i = 0 ; i < expectedTitles . length ; i ++ ) {
137
+ const item = categoryHeadings . nth ( i ) ;
138
+ await expect ( item ) . toHaveText ( expectedTitles [ i ] ) ;
139
+ const links = item . locator ( ':scope + .teach-list > li' ) ;
140
+ expect ( await links . count ( ) ) . toBeGreaterThan ( 0 ) ;
141
+ }
142
+ } ) ;
143
+
144
+ test ( 'Should have a working subscription form' , async ( { page } ) => {
145
+ const email = '[email protected] ' ;
146
+
147
+ await page . route ( 'https://forms-service.jetbrains.com/marketo' , route => {
148
+ if ( route . request ( ) . method ( ) !== 'POST' ) route . continue ( ) ;
149
+ route . fulfill ( {
150
+ status : 200 ,
151
+ contentType : 'application/json' ,
152
+ body : JSON . stringify ( { 'success' : true , 'cause' : [ ] } )
153
+ } ) ;
154
+ } ) ;
155
+
156
+ await page . route ( `https://account.jetbrains.com/services/acceptAgreement?email=${ encodeURIComponent ( email ) } &type=mkt.newsletter.visitor` , route => {
157
+ if ( route . request ( ) . method ( ) !== 'POST' ) route . continue ( ) ;
158
+ route . fulfill ( {
159
+ status : 200 ,
160
+ contentType : 'application/json' ,
161
+ body : JSON . stringify ( { 'status' : 'OK' } )
162
+ } ) ;
163
+ } ) ;
164
+
165
+ // Locate the subscription form
166
+ const subscriptionForm = page . locator ( '.teach-subscription-section' ) ;
167
+ await expect ( subscriptionForm ) . toBeVisible ( ) ;
168
+
169
+ // Find the form elements
170
+ await subscriptionForm . locator ( 'input[name="Email"]' ) . fill ( email ) ;
171
+
172
+ // Check the privacy checkbox by clicking its label
173
+ await subscriptionForm . locator ( '.teach-subscription-form__checkbox label' ) . click ( ) ;
174
+
175
+ // Submit the form
176
+ await subscriptionForm . locator ( 'button[type="submit"]' ) . click ( ) ;
177
+
178
+ // Verify that the form shows the submitted state (check icon appears)
179
+ await expect ( subscriptionForm . locator ( '.teach-subscription-form__submitted-icon' ) ) . toBeVisible ( ) ;
180
+
181
+ expect ( await subscriptionForm . screenshot ( ) ) . toMatchSnapshot ( 'subscription-form.png' ) ;
182
+ } ) ;
183
+
184
+ test ( 'Should have a working YouTube player' , async ( { page } ) => {
185
+ // Check if the YouTube player container is visible
186
+ const youtubePlayer = page . locator ( '.teach-video' ) ;
187
+ await expect ( youtubePlayer ) . toBeVisible ( ) ;
188
+
189
+ // Check if the player is in "show video" mode
190
+ await expect ( youtubePlayer . locator ( '[class*="ktl-youtube-player-module_preview_"]' ) ) . toBeVisible ( ) ;
191
+
192
+ // Check if the play button is visible
193
+ const playButton = youtubePlayer . locator ( '[class*="ktl-youtube-player-module_play-button_"]' ) ;
194
+ await expect ( playButton ) . toBeVisible ( ) ;
195
+
196
+ // Click the play button to start the video
197
+ await playButton . click ( ) ;
198
+
199
+ // After clicking, the play button should be hidden and the video should be playing
200
+ await expect ( playButton ) . toBeHidden ( ) ;
201
+
202
+ // Check if the iframe is loaded correctly
203
+ const iframe = youtubePlayer . locator ( 'iframe' ) ;
204
+ await expect ( iframe ) . toBeVisible ( ) ;
205
+
206
+ // Check if the iframe has the correct src attribute (YouTube embed URL)
207
+ const iframeSrc = await iframe . getAttribute ( 'src' ) ;
208
+ expect ( iframeSrc ) . toBeTruthy ( ) ;
209
+ expect ( iframeSrc ) . toContain ( 'youtube.com' ) ;
210
+ expect ( iframeSrc ) . toContain ( 'PLlFc5cFwUnmzT4cgLOGJYGnY6j0W2xoFA' ) ;
211
+ } ) ;
212
+
213
+ test ( 'Should have working quotes slider' , async ( { page } ) => {
214
+ const quotes = page . locator ( '[class*=ktl-quotes-slider-module_quotes-slider_]' ) ;
215
+
216
+ // Initial state of quotes
217
+ const defaultAuthor = quotes . getByText ( 'David Vaughn' , { exact : false } ) ;
218
+ await expect ( defaultAuthor ) . toBeVisible ( ) ;
219
+
220
+ const quoteContent = quotes . getByText ( 'Kotlin is faster to develop' , { exact : false } ) ;
221
+ await expect ( quoteContent ) . toBeVisible ( ) ;
222
+
223
+ // Controls of navigation
224
+ const controls = page . locator ( '[class*=ktl-quotes-slider-module_control_]' ) ;
225
+ await expect ( controls ) . toHaveCount ( 2 ) ;
226
+
227
+ const backButton = controls . first ( ) ;
228
+ await expect ( backButton ) . not . toHaveClass ( / k t l - q u o t e s - s l i d e r - m o d u l e _ c o n t r o l - a c t i v e _ / ) ;
229
+
230
+ const forwardButton = controls . last ( ) ;
231
+ await expect ( forwardButton ) . toHaveClass ( / k t l - q u o t e s - s l i d e r - m o d u l e _ c o n t r o l - a c t i v e _ / ) ;
232
+
233
+ await forwardButton . click ( ) ;
234
+
235
+ await expect ( quotes . getByText ( 'Sergey Bratus' ) ) . toBeVisible ( ) ;
236
+ await expect ( quotes . getByText ( 'I used Kotlin' ) ) . toBeVisible ( ) ;
237
+
238
+ await expect ( backButton ) . toHaveClass ( / k t l - q u o t e s - s l i d e r - m o d u l e _ c o n t r o l - a c t i v e _ / ) ;
239
+ } ) ;
240
+
241
+ test ( 'Should have action buttons for educators' , checkTeachCta ) ;
242
+ } ) ;
0 commit comments