Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 1 | /// <reference types="cypress" /> |
| 2 | |
Philipp Schrader | e11114f | 2023-04-15 17:04:25 -0700 | [diff] [blame] | 3 | // On the 87th row of matches (index 86) click on the second team |
| 4 | // (index 1) which resolves to team 5254 in semi final 2 match 3. |
| 5 | const SEMI_FINAL_2_MATCH_3_TEAM_5254 = 86 * 6 + 1; |
| 6 | |
| 7 | // On the 1st row of matches (index 0) click on the fourth team |
| 8 | // (index 3) which resolves to team 3990 in quals match 1. |
| 9 | const QUALS_MATCH_1_TEAM_3990 = 0 * 6 + 3; |
| 10 | |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 11 | function disableAlerts() { |
| 12 | cy.get('#block_alerts').check({force: true}).should('be.checked'); |
| 13 | } |
| 14 | |
| 15 | function switchToTab(tabName) { |
| 16 | cy.contains('.nav-link', tabName).click(); |
| 17 | } |
| 18 | |
| 19 | function headerShouldBe(text) { |
| 20 | cy.get('.header').should('have.text', text); |
| 21 | } |
| 22 | |
| 23 | function clickButton(buttonName) { |
| 24 | cy.contains('button', buttonName).click(); |
| 25 | } |
| 26 | |
| 27 | function setInputTo(fieldSelector, value) { |
| 28 | cy.get(fieldSelector).type('{selectAll}' + value); |
| 29 | } |
| 30 | |
| 31 | // Moves the nth slider left or right. A positive "adjustBy" value moves the |
| 32 | // slider to the right. A negative value moves the slider to the left. |
| 33 | // |
| 34 | // negative/left <--- 0 ---> positive/right |
| 35 | function adjustNthSliderBy(n, adjustBy) { |
| 36 | let element = cy.get('input[type=range]').eq(n); |
| 37 | element.scrollIntoView(); |
| 38 | element.invoke('val').then((currentValue) => { |
| 39 | // We need to query for the slider here again because `invoke('val')` above |
| 40 | // somehow invalidates further calls to `val`. |
| 41 | cy.get('input[type=range]') |
| 42 | .eq(n) |
| 43 | .invoke('val', currentValue + adjustBy) |
| 44 | .trigger('change'); |
| 45 | }); |
| 46 | } |
| 47 | |
| 48 | // Asserts that the field on the "Submit and Review" screen has a specific |
| 49 | // value. |
| 50 | function expectReviewFieldToBe(fieldName, expectedValue) { |
| 51 | expectNthReviewFieldToBe(fieldName, 0, expectedValue); |
| 52 | } |
| 53 | |
| 54 | // Asserts that the n'th instance of a field on the "Submit and Review" |
| 55 | // screen has a specific value. |
| 56 | function expectNthReviewFieldToBe(fieldName, n, expectedValue) { |
| 57 | getNthReviewField(fieldName, n).should( |
| 58 | 'have.text', |
| 59 | `${fieldName}: ${expectedValue}` |
| 60 | ); |
| 61 | } |
| 62 | |
| 63 | function getNthReviewField(fieldName, n) { |
| 64 | let element = cy.get('li').filter(`:contains("${fieldName}: ")`).eq(n); |
| 65 | element.scrollIntoView(); |
| 66 | return element; |
| 67 | } |
| 68 | |
| 69 | before(() => { |
| 70 | cy.visit('/'); |
| 71 | disableAlerts(); |
| 72 | cy.title().should('eq', 'FRC971 Scouting Application'); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 73 | }); |
| 74 | |
| 75 | beforeEach(() => { |
| 76 | cy.visit('/'); |
| 77 | disableAlerts(); |
| 78 | }); |
| 79 | |
| 80 | describe('Scouting app tests', () => { |
| 81 | it('should: show matches in chronological order.', () => { |
| 82 | headerShouldBe('Matches'); |
| 83 | cy.get('.badge').eq(0).contains('Quals Match 1'); |
| 84 | cy.get('.badge').eq(1).contains('Quals Match 2'); |
| 85 | cy.get('.badge').eq(2).contains('Quals Match 3'); |
| 86 | cy.get('.badge').eq(9).contains('Quals Match 10'); |
| 87 | cy.get('.badge').eq(72).contains('Quarter Final 1 Match 1'); |
| 88 | cy.get('.badge').eq(73).contains('Quarter Final 2 Match 1'); |
| 89 | cy.get('.badge').eq(74).contains('Quarter Final 3 Match 1'); |
| 90 | cy.get('.badge').eq(75).contains('Quarter Final 4 Match 1'); |
| 91 | cy.get('.badge').eq(76).contains('Quarter Final 1 Match 2'); |
| 92 | cy.get('.badge').eq(82).contains('Semi Final 1 Match 1'); |
| 93 | cy.get('.badge').eq(83).contains('Semi Final 2 Match 1'); |
| 94 | cy.get('.badge').eq(84).contains('Semi Final 1 Match 2'); |
| 95 | cy.get('.badge').eq(85).contains('Semi Final 2 Match 2'); |
| 96 | cy.get('.badge').eq(89).contains('Final 1 Match 3'); |
| 97 | }); |
| 98 | |
Philipp Schrader | 8702b78 | 2023-04-15 17:33:37 -0700 | [diff] [blame^] | 99 | it('should: prevent users from enter invalid match information.', () => { |
| 100 | switchToTab('Entry'); |
| 101 | headerShouldBe(' Team Selection '); |
| 102 | |
| 103 | setInputTo('#match_number', '1'); |
| 104 | setInputTo('#team_number', '5254'); |
| 105 | setInputTo('#set_number', '1'); |
| 106 | cy.get('#comp_level').select('Qualifications'); |
| 107 | |
| 108 | cy.contains('button', 'Next').should('be.disabled'); |
| 109 | }); |
| 110 | |
| 111 | it('should: let users enter match information manually.', () => { |
Philipp Schrader | 75021f5 | 2023-04-09 21:14:13 -0700 | [diff] [blame] | 112 | switchToTab('Entry'); |
Philipp Schrader | 2b33427 | 2023-04-11 21:27:36 -0700 | [diff] [blame] | 113 | headerShouldBe(' Team Selection '); |
Philipp Schrader | 75021f5 | 2023-04-09 21:14:13 -0700 | [diff] [blame] | 114 | |
| 115 | setInputTo('#match_number', '3'); |
| 116 | setInputTo('#team_number', '5254'); |
| 117 | setInputTo('#set_number', '2'); |
Philipp Schrader | 8702b78 | 2023-04-15 17:33:37 -0700 | [diff] [blame^] | 118 | cy.get('#comp_level').select('Semi Finals'); |
Philipp Schrader | 75021f5 | 2023-04-09 21:14:13 -0700 | [diff] [blame] | 119 | |
| 120 | clickButton('Next'); |
| 121 | |
| 122 | headerShouldBe('5254 Init '); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 123 | }); |
| 124 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 125 | //TODO(FILIP): Verify last action when the last action header gets added. |
Sabina Leaver | 9b4eb31 | 2023-02-20 19:58:17 -0800 | [diff] [blame] | 126 | it('should: be able to submit data scouting.', () => { |
Philipp Schrader | e11114f | 2023-04-15 17:04:25 -0700 | [diff] [blame] | 127 | // Click on a random team in the Match list. The exact details here are not |
| 128 | // important, but we need to know what they are. This could as well be any |
| 129 | // other team from any other match. |
| 130 | cy.get('button.match-item').eq(SEMI_FINAL_2_MATCH_3_TEAM_5254).click(); |
Philipp Schrader | 2b33427 | 2023-04-11 21:27:36 -0700 | [diff] [blame] | 131 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 132 | // Select Starting Position. |
Philipp Schrader | 2b33427 | 2023-04-11 21:27:36 -0700 | [diff] [blame] | 133 | headerShouldBe('5254 Init '); |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 134 | cy.get('[type="radio"]').first().check(); |
| 135 | clickButton('Start Match'); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 136 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 137 | // Pick and Place Cone in Auto. |
| 138 | clickButton('CONE'); |
| 139 | clickButton('HIGH'); |
| 140 | |
| 141 | // Pick and Place Cube in Teleop. |
| 142 | clickButton('Start Teleop'); |
| 143 | clickButton('CUBE'); |
| 144 | clickButton('LOW'); |
| 145 | |
| 146 | // Robot dead and revive. |
| 147 | clickButton('DEAD'); |
| 148 | clickButton('Revive'); |
| 149 | |
Philipp Schrader | e11114f | 2023-04-15 17:04:25 -0700 | [diff] [blame] | 150 | // Endgame. |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 151 | clickButton('Endgame'); |
| 152 | cy.get('[type="checkbox"]').check(); |
| 153 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 154 | clickButton('End Match'); |
Philipp Schrader | 2b33427 | 2023-04-11 21:27:36 -0700 | [diff] [blame] | 155 | headerShouldBe('5254 Review and Submit '); |
Sabina Leaver | 9b4eb31 | 2023-02-20 19:58:17 -0800 | [diff] [blame] | 156 | |
| 157 | clickButton('Submit'); |
Philipp Schrader | 2b33427 | 2023-04-11 21:27:36 -0700 | [diff] [blame] | 158 | headerShouldBe('5254 Success '); |
Philipp Schrader | e11114f | 2023-04-15 17:04:25 -0700 | [diff] [blame] | 159 | |
| 160 | // Now that the data is submitted, the button should be disabled. |
| 161 | switchToTab('Match List'); |
| 162 | cy.get('button.match-item') |
| 163 | .eq(SEMI_FINAL_2_MATCH_3_TEAM_5254) |
| 164 | .should('be.disabled'); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 165 | }); |
| 166 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 167 | it('should: be able to return to correct screen with undo for pick and place.', () => { |
Philipp Schrader | e11114f | 2023-04-15 17:04:25 -0700 | [diff] [blame] | 168 | cy.get('button.match-item').eq(QUALS_MATCH_1_TEAM_3990).click(); |
Philipp Schrader | 2b33427 | 2023-04-11 21:27:36 -0700 | [diff] [blame] | 169 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 170 | // Select Starting Position. |
| 171 | cy.get('[type="radio"]').first().check(); |
| 172 | clickButton('Start Match'); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 173 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 174 | // Pick up cone. |
| 175 | clickButton('CONE'); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 176 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 177 | // Undo that pick up. |
| 178 | clickButton('UNDO'); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 179 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 180 | // User should be back on pickup screen. |
Philipp Schrader | e11114f | 2023-04-15 17:04:25 -0700 | [diff] [blame] | 181 | headerShouldBe('3990 Pickup '); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 182 | |
Filip Kujawa | 2dc9aa6 | 2023-03-04 11:45:01 -0800 | [diff] [blame] | 183 | // Check the same thing but for undoing place. |
| 184 | clickButton('CUBE'); |
| 185 | clickButton('MID'); |
| 186 | clickButton('UNDO'); |
Philipp Schrader | e11114f | 2023-04-15 17:04:25 -0700 | [diff] [blame] | 187 | headerShouldBe('3990 Place '); |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 188 | }); |
| 189 | |
Philipp Schrader | 175a93c | 2023-02-19 13:13:40 -0800 | [diff] [blame] | 190 | it('should: submit note scouting for multiple teams', () => { |
| 191 | // Navigate to Notes Page. |
| 192 | switchToTab('Notes'); |
| 193 | headerShouldBe('Notes'); |
| 194 | |
| 195 | // Add first team. |
| 196 | setInputTo('#team_number_notes', '1234'); |
| 197 | clickButton('Select'); |
| 198 | |
| 199 | // Add note and select keyword for first team. |
| 200 | cy.get('#team-key-1').should('have.text', '1234'); |
| 201 | setInputTo('#text-input-1', 'Good Driving'); |
| 202 | cy.get('#good_driving_0').click(); |
| 203 | |
| 204 | // Navigate to add team selection and add another team. |
| 205 | clickButton('Add team'); |
| 206 | setInputTo('#team_number_notes', '1235'); |
| 207 | clickButton('Select'); |
| 208 | |
| 209 | // Add note and select keyword for second team. |
| 210 | cy.get('#team-key-2').should('have.text', '1235'); |
| 211 | setInputTo('#text-input-2', 'Bad Driving'); |
| 212 | cy.get('#bad_driving_1').click(); |
| 213 | |
| 214 | // Submit Notes. |
| 215 | clickButton('Submit'); |
| 216 | cy.get('#team_number_label').should('have.text', ' Team Number '); |
| 217 | }); |
| 218 | |
| 219 | it('should: switch note text boxes with keyboard shortcuts', () => { |
| 220 | // Navigate to Notes Page. |
| 221 | switchToTab('Notes'); |
| 222 | headerShouldBe('Notes'); |
| 223 | |
| 224 | // Add first team. |
| 225 | setInputTo('#team_number_notes', '1234'); |
| 226 | clickButton('Select'); |
| 227 | |
| 228 | // Add second team. |
| 229 | clickButton('Add team'); |
| 230 | setInputTo('#team_number_notes', '1235'); |
| 231 | clickButton('Select'); |
| 232 | |
| 233 | // Add third team. |
| 234 | clickButton('Add team'); |
| 235 | setInputTo('#team_number_notes', '1236'); |
| 236 | clickButton('Select'); |
| 237 | |
| 238 | for (let i = 1; i <= 3; i++) { |
| 239 | // Press Control + i |
| 240 | cy.get('body').type(`{ctrl}${i}`); |
| 241 | |
| 242 | // Expect text input to be focused. |
| 243 | cy.focused().then(($element) => { |
| 244 | expect($element).to.have.id(`text-input-${i}`); |
| 245 | }); |
| 246 | } |
| 247 | }); |
| 248 | |
| 249 | it('should: submit driver ranking', () => { |
| 250 | // Navigate to Driver Ranking Page. |
| 251 | switchToTab('Driver Ranking'); |
| 252 | headerShouldBe('Driver Ranking'); |
| 253 | |
| 254 | // Input match and team numbers. |
| 255 | setInputTo('#match_number_selection', '11'); |
| 256 | setInputTo('#team_input_0', '123'); |
| 257 | setInputTo('#team_input_1', '456'); |
| 258 | setInputTo('#team_input_2', '789'); |
| 259 | clickButton('Select'); |
| 260 | |
| 261 | // Verify match and team key input. |
| 262 | cy.get('#match_number_heading').should('have.text', 'Match #11'); |
| 263 | cy.get('#team_key_label_0').should('have.text', ' 123 '); |
| 264 | cy.get('#team_key_label_1').should('have.text', ' 456 '); |
| 265 | cy.get('#team_key_label_2').should('have.text', ' 789 '); |
| 266 | |
| 267 | // Rank teams. |
| 268 | cy.get('#up_button_2').click(); |
| 269 | cy.get('#down_button_0').click(); |
| 270 | |
| 271 | // Verify ranking change. |
| 272 | cy.get('#team_key_label_0').should('have.text', ' 789 '); |
| 273 | cy.get('#team_key_label_1').should('have.text', ' 123 '); |
| 274 | cy.get('#team_key_label_2').should('have.text', ' 456 '); |
| 275 | |
| 276 | // Submit. |
| 277 | clickButton('Submit'); |
| 278 | }); |
| 279 | }); |