1
1
/// <reference types="cypress" />
2
+
2
3
describe ( 'Article links' , ( ) => {
3
4
const subjects = Cypress . env ( 'test_subjects' ) . split ( ',' ) ;
5
+ // Always use HEAD for downloads to avoid timeouts
6
+ const useHeadForDownloads = true ;
7
+
8
+ // Helper function to identify download links - improved
9
+ function isDownloadLink ( href ) {
10
+ // Check for common download file extensions
11
+ const downloadExtensions = [
12
+ '.pdf' , '.zip' , '.tar.gz' , '.tgz' , '.rar' , '.exe' , '.dmg' , '.pkg' ,
13
+ '.deb' , '.rpm' , '.xlsx' , '.csv' , '.doc' , '.docx' , '.ppt' , '.pptx'
14
+ ] ;
15
+
16
+ // Check for download domains or paths
17
+ const downloadDomains = [
18
+ 'dl.influxdata.com' ,
19
+ 'downloads.influxdata.com'
20
+ ] ;
21
+
22
+ // Check if URL contains a download extension
23
+ const hasDownloadExtension = downloadExtensions . some ( ext =>
24
+ href . toLowerCase ( ) . endsWith ( ext )
25
+ ) ;
26
+
27
+ // Check if URL is from a download domain
28
+ const isFromDownloadDomain = downloadDomains . some ( domain =>
29
+ href . toLowerCase ( ) . includes ( domain )
30
+ ) ;
31
+
32
+ // Return true if either condition is met
33
+ return hasDownloadExtension || isFromDownloadDomain ;
34
+ }
35
+
36
+ // Helper function to make appropriate request based on link type
37
+ function testLink ( href ) {
38
+ if ( useHeadForDownloads && isDownloadLink ( href ) ) {
39
+ cy . log ( `** Testing download link with HEAD: ${ href } **` ) ;
40
+ cy . request ( {
41
+ method : 'HEAD' ,
42
+ url : href ,
43
+ failOnStatusCode : false ,
44
+ timeout : 10000 // 10 second timeout for download links
45
+ } ) . then ( response => {
46
+ expect ( response . status ) . to . be . lt ( 400 ) ;
47
+ } ) ;
48
+ } else {
49
+ cy . log ( `** Testing link: ${ href } **` ) ;
50
+ cy . request ( {
51
+ url : href ,
52
+ failOnStatusCode : false ,
53
+ timeout : 30000 // 30 second timeout for regular links
54
+ } ) . then ( response => {
55
+ expect ( response . status ) . to . be . lt ( 400 ) ;
56
+ } ) ;
57
+ }
58
+ }
4
59
5
60
subjects . forEach ( ( subject ) => {
6
- it ( 'contains valid internal links' , function ( ) {
61
+ it ( `contains valid internal links on ${ subject } ` , function ( ) {
62
+ cy . visit ( `${ subject } ` ) ;
63
+
64
+ // Test internal links (including anchor links)
65
+ cy . get ( 'article a[href^="/"]' ) . each ( ( $a ) => {
66
+ const href = $a . attr ( 'href' ) ;
67
+ testLink ( href ) ;
68
+ } ) ;
69
+ } ) ;
70
+
71
+ it ( `checks anchor links on ${ subject } (with warnings for missing targets)` , function ( ) {
7
72
cy . visit ( `${ subject } ` ) ;
8
- cy . get ( 'article a[href^="/"]' ) //.filter('[href^="/"]')
9
- . each ( ( $a ) => {
10
- cy . log ( `** Testing internal link ${ $a . attr ( 'href' ) } **` ) ;
11
- // cy.request doesn't show in your browser's Developer Tools
12
- // because the request comes from Node, not from the browser.
13
- cy . request ( $a . attr ( 'href' ) ) . its ( 'status' ) . should ( 'eq' , 200 ) ;
14
- } ) ;
73
+
74
+ // Track missing anchors for summary
75
+ const missingAnchors = [ ] ;
76
+
77
+ // Process anchor links individually
78
+ cy . get ( 'article a[href^="#"]' ) . each ( ( $a ) => {
79
+ const href = $a . prop ( 'href' ) ; // Use prop() instead of attr()
80
+ if ( href && href . length > 1 ) { // Skip empty anchors (#)
81
+ // Get just the fragment part
82
+ const url = new URL ( href ) ;
83
+ const anchorId = url . hash . substring ( 1 ) ; // Remove the # character
84
+
85
+ if ( ! anchorId ) {
86
+ cy . log ( `Skipping empty anchor in ${ href } ` ) ;
87
+ return ;
88
+ }
89
+
90
+ // Use DOM to check if the element exists, but don't fail if missing
91
+ cy . window ( ) . then ( win => {
92
+ const element = win . document . getElementById ( anchorId ) ;
93
+ if ( element ) {
94
+ cy . log ( `✅ Anchor target exists: #${ anchorId } ` ) ;
95
+ } else {
96
+ // Just warn about the missing anchor
97
+ cy . log ( `⚠️ WARNING: Missing anchor target: #${ anchorId } ` ) ;
98
+ missingAnchors . push ( anchorId ) ;
99
+ }
100
+ } ) ;
101
+ }
102
+ } ) . then ( ( ) => {
103
+ // After checking all anchors, log a summary
104
+ if ( missingAnchors . length > 0 ) {
105
+ cy . log ( `⚠️ Found ${ missingAnchors . length } missing anchor targets: ${ missingAnchors . join ( ', ' ) } ` ) ;
106
+ } else {
107
+ cy . log ( '✅ All anchor targets are valid' ) ;
108
+ }
15
109
} ) ;
16
- it ( 'contains valid external links' , function ( ) {
110
+ } ) ;
111
+
112
+ it ( `contains valid external links on ${ subject } ` , function ( ) {
17
113
cy . visit ( `${ subject } ` ) ;
18
- cy . get ( 'article a[href^="http"]' )
19
- . each ( ( $a ) => {
20
- // cy.request doesn't show in your browser's Developer Tools
21
- cy . log ( `** Testing external link ${ $a . attr ( 'href' ) } **` ) ;
22
- // because the request comes from Node, not from the browser.
23
- cy . request ( $a . attr ( 'href' ) ) . its ( 'status' ) . should ( 'eq' , 200 ) ;
24
- } ) ;
114
+
115
+ // Test external links
116
+ cy . get ( 'article a[href^="http"]' ) . each ( ( $a ) => {
117
+ const href = $a . attr ( 'href' ) ;
118
+ testLink ( href ) ;
119
+ } ) ;
25
120
} ) ;
26
121
} ) ;
27
- } ) ;
122
+ } ) ;
0 commit comments