loading up the forgejo repo on tangled to test page performance
at forgejo 217 lines 6.6 kB view raw
1import {mount, flushPromises} from '@vue/test-utils'; 2import RepoActionView from './RepoActionView.vue'; 3 4test('processes ##[group] and ##[endgroup]', async () => { 5 Object.defineProperty(document.documentElement, 'lang', {value: 'en'}); 6 vi.spyOn(global, 'fetch').mockImplementation((url, opts) => { 7 const artifacts_value = { 8 artifacts: [], 9 }; 10 const stepsLog_value = [ 11 { 12 step: 0, 13 cursor: 0, 14 lines: [ 15 {index: 1, message: '##[group]Test group', timestamp: 0}, 16 {index: 2, message: 'A test line', timestamp: 0}, 17 {index: 3, message: '##[endgroup]', timestamp: 0}, 18 {index: 4, message: 'A line outside the group', timestamp: 0}, 19 ], 20 }, 21 ]; 22 const jobs_value = { 23 state: { 24 run: { 25 status: 'success', 26 commit: { 27 pusher: {}, 28 }, 29 }, 30 currentJob: { 31 steps: [ 32 { 33 summary: 'Test Job', 34 duration: '1s', 35 status: 'success', 36 }, 37 ], 38 }, 39 }, 40 logs: { 41 stepsLog: opts.body?.includes('"cursor":null') ? stepsLog_value : [], 42 }, 43 }; 44 45 return Promise.resolve({ 46 ok: true, 47 json: vi.fn().mockResolvedValue( 48 url.endsWith('/artifacts') ? artifacts_value : jobs_value, 49 ), 50 }); 51 }); 52 53 const wrapper = mount(RepoActionView, { 54 props: { 55 jobIndex: '1', 56 locale: { 57 approve: '', 58 cancel: '', 59 rerun: '', 60 artifactsTitle: '', 61 areYouSure: '', 62 confirmDeleteArtifact: '', 63 rerun_all: '', 64 showTimeStamps: '', 65 showLogSeconds: '', 66 showFullScreen: '', 67 downloadLogs: '', 68 status: { 69 unknown: '', 70 waiting: '', 71 running: '', 72 success: '', 73 failure: '', 74 cancelled: '', 75 skipped: '', 76 blocked: '', 77 }, 78 }, 79 }, 80 }); 81 await flushPromises(); 82 await wrapper.get('.job-step-summary').trigger('click'); 83 await flushPromises(); 84 85 // Test if header was loaded correctly 86 expect(wrapper.get('.step-summary-msg').text()).toEqual('Test Job'); 87 88 // Check if 3 lines where rendered 89 expect(wrapper.findAll('.job-log-line').length).toEqual(3); 90 91 // Check if line 1 contains the group header 92 expect(wrapper.get('.job-log-line:nth-of-type(1) > details.log-msg').text()).toEqual('Test group'); 93 94 // Check if right after the header line exists a log list 95 expect(wrapper.find('.job-log-line:nth-of-type(1) + .job-log-list.hidden').exists()).toBe(true); 96 97 // Check if inside the loglist exist exactly one log line 98 expect(wrapper.findAll('.job-log-list > .job-log-line').length).toEqual(1); 99 100 // Check if inside the loglist is an logline with our second logline 101 expect(wrapper.get('.job-log-list > .job-log-line > .log-msg').text()).toEqual('A test line'); 102 103 // Check if after the log list exists another log line 104 expect(wrapper.get('.job-log-list + .job-log-line > .log-msg').text()).toEqual('A line outside the group'); 105}); 106 107test('load multiple steps on a finished action', async () => { 108 Object.defineProperty(document.documentElement, 'lang', {value: 'en'}); 109 vi.spyOn(global, 'fetch').mockImplementation((url, opts) => { 110 if (url.endsWith('/artifacts')) { 111 return Promise.resolve({ 112 ok: true, 113 json: vi.fn().mockResolvedValue( 114 { 115 artifacts: [], 116 }, 117 ), 118 }); 119 } 120 121 const postBody = JSON.parse(opts.body); 122 const stepsLog_value = []; 123 for (const cursor of postBody.logCursors) { 124 if (cursor.expanded) { 125 stepsLog_value.push( 126 { 127 step: cursor.step, 128 cursor: 0, 129 lines: [ 130 {index: 1, message: `Step #${cursor.step + 1} Log #1`, timestamp: 0}, 131 {index: 1, message: `Step #${cursor.step + 1} Log #2`, timestamp: 0}, 132 {index: 1, message: `Step #${cursor.step + 1} Log #3`, timestamp: 0}, 133 ], 134 }, 135 ); 136 } 137 } 138 const jobs_value = { 139 state: { 140 run: { 141 status: 'success', 142 commit: { 143 pusher: {}, 144 }, 145 }, 146 currentJob: { 147 steps: [ 148 { 149 summary: 'Test Step #1', 150 duration: '1s', 151 status: 'success', 152 }, 153 { 154 summary: 'Test Step #2', 155 duration: '1s', 156 status: 'success', 157 }, 158 ], 159 }, 160 }, 161 logs: { 162 stepsLog: opts.body?.includes('"cursor":null') ? stepsLog_value : [], 163 }, 164 }; 165 166 return Promise.resolve({ 167 ok: true, 168 json: vi.fn().mockResolvedValue( 169 jobs_value, 170 ), 171 }); 172 }); 173 174 const wrapper = mount(RepoActionView, { 175 props: { 176 actionsURL: 'https://example.com/example-org/example-repo/actions', 177 runIndex: '1', 178 jobIndex: '2', 179 locale: { 180 approve: '', 181 cancel: '', 182 rerun: '', 183 artifactsTitle: '', 184 areYouSure: '', 185 confirmDeleteArtifact: '', 186 rerun_all: '', 187 showTimeStamps: '', 188 showLogSeconds: '', 189 showFullScreen: '', 190 downloadLogs: '', 191 status: { 192 unknown: '', 193 waiting: '', 194 running: '', 195 success: '', 196 failure: '', 197 cancelled: '', 198 skipped: '', 199 blocked: '', 200 }, 201 }, 202 }, 203 }); 204 await flushPromises(); 205 // Click on both steps to start their log loading in fast succession... 206 await wrapper.get('.job-step-section:nth-of-type(1) .job-step-summary').trigger('click'); 207 await wrapper.get('.job-step-section:nth-of-type(2) .job-step-summary').trigger('click'); 208 await flushPromises(); 209 210 // Verify both step's logs were loaded 211 expect(wrapper.get('.job-step-section:nth-of-type(1) .job-log-line:nth-of-type(1) .log-msg').text()).toEqual('Step #1 Log #1'); 212 expect(wrapper.get('.job-step-section:nth-of-type(1) .job-log-line:nth-of-type(2) .log-msg').text()).toEqual('Step #1 Log #2'); 213 expect(wrapper.get('.job-step-section:nth-of-type(1) .job-log-line:nth-of-type(3) .log-msg').text()).toEqual('Step #1 Log #3'); 214 expect(wrapper.get('.job-step-section:nth-of-type(2) .job-log-line:nth-of-type(1) .log-msg').text()).toEqual('Step #2 Log #1'); 215 expect(wrapper.get('.job-step-section:nth-of-type(2) .job-log-line:nth-of-type(2) .log-msg').text()).toEqual('Step #2 Log #2'); 216 expect(wrapper.get('.job-step-section:nth-of-type(2) .job-log-line:nth-of-type(3) .log-msg').text()).toEqual('Step #2 Log #3'); 217});