Something went wrong. Try again.
Bluesky app fork with some witchin' additions 💫
Something went wrong. Try again.
5.3 kB · 194 lines
JavaScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195import assert from 'node:assert/strict'import test from 'node:test'
import {buildSlackMessage, extractSlackFileIds} from './maestro-slack.mjs'import {screenshotsByFlow} from './summarize-maestro.mjs'
function platform({ name, status = 'success', failed = false, failures = [], phase = 'Completed', hasJUnit = true,}) { return { name, status, failed, failures, phase, hasJUnit, artifactUrl: `https://example.com/${name.toLowerCase()}`, }}
function build(platforms, slackFileIds = []) { return buildSlackMessage({ platforms, sha: '1234567890abcdef', runUrl: 'https://example.com/run', commitUrl: 'https://example.com/commit', slackFileIds, })}
test('builds a screenshot carousel for failed flows', () => { const platforms = [ platform({ name: 'iOS', status: 'failure', failed: true, failures: [ { name: 'composer', message: 'Element not found', screenshot: '/tmp/screenshot-(composer).png', }, ], }), platform({name: 'Android'}), ] const summary = build(platforms, ['F123ABC']) const carousel = summary.payload.blocks.find( block => block.type === 'carousel', )
assert.equal(summary.state, 'failed') assert.equal(summary.screenshotCount, 1) assert.equal( summary.uploadPayload.file_uploads[0].file, platforms[0].failures[0].screenshot, ) assert.equal(summary.uploadPayload.file_uploads[0].highlight_type, 'png') assert.deepEqual(carousel.elements[0].hero_image.slack_file, {id: 'F123ABC'})})
test('selects failures across both platforms for the carousel', () => { const failures = prefix => Array.from({length: 7}, (_, index) => ({ name: `${prefix}-${index}`, message: 'Failed', screenshot: `/tmp/${prefix}-${index}.png`, })) const summary = build([ platform({ name: 'iOS', status: 'failure', failed: true, failures: failures('ios'), }), platform({ name: 'Android', status: 'failure', failed: true, failures: failures('android'), }), ]) const carousel = summary.payload.blocks.find( block => block.type === 'carousel', )
assert.equal(carousel.elements.length, 10) assert.equal(summary.failureCount, 14) assert.equal(summary.screenshotCount, 14) assert.equal(summary.uploadPayload.file_uploads.length, 14) assert.match(summary.threadPayload.text, /ios-6/) assert.match(summary.threadPayload.text, /android-6/) assert.equal(carousel.elements[0].subtitle.text, 'iOS · failed flow') assert.equal(carousel.elements[1].subtitle.text, 'Android · failed flow')})
test('uses a cancellation presentation for partial results', () => { const summary = build([ platform({ name: 'iOS', status: 'cancelled', failed: true, failures: [], phase: 'Building iOS development client', hasJUnit: false, }), platform({ name: 'Android', status: 'cancelled', failed: true, failures: [], phase: 'Building Android development client', hasJUnit: false, }), ])
assert.equal(summary.state, 'cancelled') assert.equal( summary.payload.blocks[0].text.text, '⏹️ Nightly Maestro E2E cancelled', ) assert.match(summary.payload.text, /cancelled/) assert.equal(summary.screenshotCount, 0)})
test('distinguishes setup failures from failed Maestro flows', () => { const summary = build([ platform({ name: 'iOS', status: 'failure', failed: true, failures: [], phase: 'Starting Metro', hasJUnit: false, }), platform({name: 'Android', status: 'skipped'}), ])
assert.equal(summary.state, 'setup_failed') assert.equal( summary.payload.blocks[0].text.text, '⚠️ Nightly Maestro setup failed', ) assert.equal( summary.payload.blocks.some(block => block.type === 'carousel'), false, )})
test('extracts file ids from single and multi-file upload responses', () => { const response = { ok: true, files: [ { ok: true, files: [{id: 'FONE'}, {id: 'FTWO'}], }, ], }
assert.deepEqual(extractSlackFileIds(response), ['FONE', 'FTWO']) assert.deepEqual( extractSlackFileIds(JSON.stringify({ok: true, files: [{id: 'FTHREE'}]})), ['FTHREE'], ) assert.deepEqual(extractSlackFileIds('not json'), [])})
test('selects the newest Maestro screenshot for each flow', () => { const screenshots = screenshotsByFlow([ '/tmp/screenshot-❌-300-(composer).png', '/tmp/screenshot-❌-100-(composer).png', '/tmp/screenshot-❌-200-(login).png', '/tmp/artifacts/maestro/composer-self-label/screenshots/step-020-tapOnElement-openMediaBtn.png', '/tmp/artifacts/maestro/composer-self-label/screenshots/step-010-launchApp.png', '/tmp/not-a-maestro-screenshot.png', ])
assert.equal( screenshots.get('composer'), '/tmp/screenshot-❌-300-(composer).png', ) assert.equal(screenshots.get('login'), '/tmp/screenshot-❌-200-(login).png') assert.equal( screenshots.get('composer-self-label'), '/tmp/artifacts/maestro/composer-self-label/screenshots/step-020-tapOnElement-openMediaBtn.png', ) assert.equal(screenshots.size, 3)})