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