diff --git a/client/components/AddTestToQueueWithConfirmation/index.jsx b/client/components/AddTestToQueueWithConfirmation/index.jsx index 4add46dfc..9b58541ff 100644 --- a/client/components/AddTestToQueueWithConfirmation/index.jsx +++ b/client/components/AddTestToQueueWithConfirmation/index.jsx @@ -323,8 +323,16 @@ function AddTestToQueueWithConfirmation({ AddTestToQueueWithConfirmation.propTypes = { testPlanVersion: PropTypes.object, - browser: PropTypes.object, - at: PropTypes.object, + browser: PropTypes.shape({ + id: PropTypes.string.isRequired, + key: PropTypes.string.isRequired, + name: PropTypes.string.isRequired + }), + at: PropTypes.shape({ + id: PropTypes.string.isRequired, + key: PropTypes.string.isRequired, + name: PropTypes.string.isRequired + }), buttonRef: PropTypes.object, onFocus: PropTypes.func, onBlur: PropTypes.func, diff --git a/client/components/DataManagement/queries.js b/client/components/DataManagement/queries.js index 6dd3d3aaa..a77e69e4f 100644 --- a/client/components/DataManagement/queries.js +++ b/client/components/DataManagement/queries.js @@ -9,9 +9,11 @@ export const DATA_MANAGEMENT_PAGE_QUERY = gql` } ats { id + key name browsers { id + key name } atVersions { @@ -66,10 +68,12 @@ export const DATA_MANAGEMENT_PAGE_QUERY = gql` markedFinalAt at { id + key name } browser { id + key name } issues { @@ -135,10 +139,12 @@ export const UPDATE_TEST_PLAN_VERSION_PHASE = gql` id at { id + key name } browser { id + key name } issues { @@ -182,10 +188,12 @@ export const UPDATE_TEST_PLAN_VERSION_RECOMMENDED_TARGET_DATE = gql` id at { id + key name } browser { id + key name } issues { diff --git a/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx b/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx index 075caddd6..586c7270d 100644 --- a/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx +++ b/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx @@ -52,7 +52,7 @@ StopRunningCollectionButton.propTypes = { 'CANCELLED', 'COMPLETED', 'ERROR' - ]) + ]).isRequired }), onClick: PropTypes.func }; diff --git a/client/components/ManageTestQueue/index.jsx b/client/components/ManageTestQueue/index.jsx index cd5aee9c2..de76dbf08 100644 --- a/client/components/ManageTestQueue/index.jsx +++ b/client/components/ManageTestQueue/index.jsx @@ -738,7 +738,20 @@ const ManageTestQueue = ({ }; ManageTestQueue.propTypes = { - ats: PropTypes.array, + ats: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + key: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + browsers: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + key: PropTypes.string.isRequired, + name: PropTypes.string.isRequired + }) + ).isRequired + }) + ).isRequired, testPlanVersions: PropTypes.array, triggerUpdate: PropTypes.func }; diff --git a/client/components/TestQueue/AssignTesterDropdown/index.jsx b/client/components/TestQueue/AssignTesterDropdown/index.jsx index a36a82b5d..73a3f6e68 100644 --- a/client/components/TestQueue/AssignTesterDropdown/index.jsx +++ b/client/components/TestQueue/AssignTesterDropdown/index.jsx @@ -148,16 +148,28 @@ const AssignTesterDropdown = ({ {possibleTesters?.length ? ( possibleTesters.map(tester => { - const { username } = tester; + const { username, isBot, ats } = tester; const testerIsAssigned = isTesterAssigned(username); const classname = [ testerIsAssigned ? 'assigned' : 'not-assigned', - tester.isBot ? 'bot' : 'human' + isBot ? 'bot' : 'human' ].join(' '); let icon; if (testerIsAssigned) { icon = faCheck; - } else if (tester.isBot) { + } else if (isBot) { + // if our bot doesn't have a link to the at - hide it from the list + if ( + !ats.find( + ({ id }) => + id === + testPlanReportAtBrowserQuery + ?.testPlanReport.at.id + ) + ) { + return null; + } + const supportedByBot = isSupportedByResponseCollector( testPlanReportAtBrowserQuery?.testPlanReport @@ -211,7 +223,19 @@ const AssignTesterDropdown = ({ AssignTesterDropdown.propTypes = { testPlanReportId: PropTypes.string.isRequired, - possibleTesters: PropTypes.array.isRequired, + possibleTesters: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + username: PropTypes.string.isRequired, + isBot: PropTypes.bool.isRequired, + ats: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + key: PropTypes.string.isRequired + }) + ) + }) + ).isRequired, onChange: PropTypes.func.isRequired, testPlanRun: PropTypes.object, label: PropTypes.string, diff --git a/client/components/TestQueue/queries.js b/client/components/TestQueue/queries.js index 51d57a5f8..f0abcd495 100644 --- a/client/components/TestQueue/queries.js +++ b/client/components/TestQueue/queries.js @@ -12,10 +12,15 @@ export const TEST_QUEUE_PAGE_QUERY = gql` username roles isBot + ats { + id + key + } } ats { id name + key atVersions { id name @@ -23,6 +28,7 @@ export const TEST_QUEUE_PAGE_QUERY = gql` } browsers { id + key name } candidateBrowsers { @@ -55,10 +61,12 @@ export const TEST_QUEUE_PAGE_QUERY = gql` markedFinalAt at { id + key name } browser { id + key name } testPlanVersion { @@ -106,10 +114,12 @@ export const TEST_PLAN_REPORT_QUERY = gql` runnableTestsLength at { id + key name } browser { id + key name } testPlanVersion { @@ -151,10 +161,12 @@ export const TEST_PLAN_REPORT_AT_BROWSER_QUERY = gql` id at { id + key name } browser { id + key name } } diff --git a/client/tests/AddTestToQueueWithConfirmation.test.jsx b/client/tests/AddTestToQueueWithConfirmation.test.jsx index 9580e7e66..9a6fa86be 100644 --- a/client/tests/AddTestToQueueWithConfirmation.test.jsx +++ b/client/tests/AddTestToQueueWithConfirmation.test.jsx @@ -35,10 +35,12 @@ const mockTestPlanReportsQueryResult = { }, isFinal: false, at: { - id: '1' + id: '1', + key: 'jaws' }, browser: { - id: '2' + id: '2', + key: 'firefox' } } ] @@ -64,8 +66,8 @@ const setup = (props, mockMutation) => { const commonSetup = mockMutation => { mockTestPlanVersion = { id: 5 }; - mockBrowser = { id: 2 }; - mockAt = { id: 3 }; + mockBrowser = { id: '2', key: 'firefox', name: 'Firefox' }; + mockAt = { id: '3', key: 'voiceover_macos', name: 'VoiceOver' }; mockButtonText = 'Add to Test Queue'; const renderResult = setup( diff --git a/client/tests/AssignTesterDropdown.test.jsx b/client/tests/AssignTesterDropdown.test.jsx index 032b98235..1768b0867 100644 --- a/client/tests/AssignTesterDropdown.test.jsx +++ b/client/tests/AssignTesterDropdown.test.jsx @@ -28,9 +28,20 @@ jest.mock('@apollo/client', () => { }); const mockPossibleTesters = [ - { id: '1', username: 'bee', isBot: false }, - { id: '2', username: 'puppy', isBot: false }, - { id: '3', username: 'NVDA Bot', isBot: true } + { id: '1', username: 'bee', isBot: false, ats: [] }, + { id: '2', username: 'puppy', isBot: false, ats: [] }, + { + id: '9999', + username: 'NVDA Bot', + isBot: true, + ats: [{ id: '2', key: 'nvda' }] + }, + { + id: '9998', + username: 'VoiceOver Bot', + isBot: true, + ats: [{ id: '3', key: 'voiceover_macos' }] + } ]; const mockProps = { @@ -62,95 +73,130 @@ useMutation.mockImplementation(mutation => { }); // Mocked GraphQL responses -const mocks = [ - { - request: { - query: ASSIGN_TESTER_MUTATION, - variables: { - testReportId: 'report1', - testerId: '1' - } +const getMocks = (atKey, browserKey) => { + const at = { + nvda: { + id: '2', + name: 'NVDA', + key: 'nvda' }, - result: { - data: { - testPlanReport: { - assignTester: { - testPlanReport: { - draftTestPlanRuns: [ - { - initiatedByAutomation: false, - tester: { - id: '1', - username: 'bee' + jaws: { + id: '1', + name: 'JAWS', + key: 'jaws' + }, + voiceover_macos: { + id: '3', + name: 'VoiceOver for MacOS', + key: 'voiceover_macos' + } + }[atKey]; + + const browser = { + chrome: { + id: '2', + name: 'Chrome', + key: 'chrome' + }, + safari_macos: { + id: '3', + name: 'Safari for MacOS', + key: 'safari_macos' + }, + voiceover_macos: { + id: '3', + name: 'VoiceOver for MacOS', + key: 'voiceover_macos' + } + }[browserKey]; + + if (!at) throw new Error('Unsupported AT key for mocks'); + if (!browser) throw new Error('Unsupported browser key for mocks'); + + return [ + { + request: { + query: ASSIGN_TESTER_MUTATION, + variables: { + testReportId: 'report1', + testerId: '1' + } + }, + result: { + data: { + testPlanReport: { + assignTester: { + testPlanReport: { + draftTestPlanRuns: [ + { + initiatedByAutomation: false, + tester: { + id: '1', + username: 'bee' + } } - } - ] + ] + } } } } } - } - }, - { - request: { - query: REMOVE_TESTER_MUTATION, - variables: { - testReportId: 'report1', - testerId: '1' - } }, - result: { - data: { - testPlanReport: { - deleteTestPlanRun: { - testPlanReport: { - draftTestPlanRuns: [] + { + request: { + query: REMOVE_TESTER_MUTATION, + variables: { + testReportId: 'report1', + testerId: '1' + } + }, + result: { + data: { + testPlanReport: { + deleteTestPlanRun: { + testPlanReport: { + draftTestPlanRuns: [] + } } } } } - } - }, - { - request: { - query: SCHEDULE_COLLECTION_JOB_MUTATION, - variables: { - testPlanReportId: 'report1' - } }, - result: { - data: { - scheduleCollectionJob: { - id: 'some-job-id', - status: 'pending' + { + request: { + query: SCHEDULE_COLLECTION_JOB_MUTATION, + variables: { + testPlanReportId: 'report1' + } + }, + result: { + data: { + scheduleCollectionJob: { + id: 'some-job-id', + status: 'pending' + } } - } - } - }, - { - request: { - query: TEST_PLAN_REPORT_AT_BROWSER_QUERY, - variables: { - testPlanReportId: 'report1' } }, - result: { - data: { - testPlanReport: { - id: 'report1', - at: { - id: 2, - name: 'NVDA' - }, - browser: { - id: 1, - name: 'Chrome' + { + request: { + query: TEST_PLAN_REPORT_AT_BROWSER_QUERY, + variables: { + testPlanReportId: 'report1' + } + }, + result: { + data: { + testPlanReport: { + id: 'report1', + at, + browser } } } } - } -]; + ]; +}; describe('AssignTesterDropdown', () => { beforeEach(() => { @@ -159,7 +205,7 @@ describe('AssignTesterDropdown', () => { it('renders without crashing', () => { render( - + ); @@ -168,7 +214,10 @@ describe('AssignTesterDropdown', () => { it('assigns tester correctly and calls assignTester mutation', async () => { render( - + ); @@ -194,7 +243,10 @@ describe('AssignTesterDropdown', () => { it('assigns bot correctly and calls scheduleCollection mutation', async () => { render( - + ); @@ -218,11 +270,39 @@ describe('AssignTesterDropdown', () => { it('does not list bot when run does not support automation', async () => { await act(async () => { - const jawsMock = [...mocks]; - jawsMock[3].result.data.testPlanReport.at.name = 'JAWS'; + render( + + + + ); + }); + let button; + await waitFor(async () => { + button = await screen.getByRole('button', { + name: /assign testers/i + }); + }); + await act(async () => { + fireEvent.click(button); + }); + + await waitFor(async () => { + const items = await screen.queryByText(/NVDA Bot/); + expect(items).toBeNull(); + }); + }); + + it('only lists supported bot', async () => { + await act(async () => { render( - + ); @@ -242,6 +322,11 @@ describe('AssignTesterDropdown', () => { const items = await screen.queryByText(/NVDA Bot/); expect(items).toBeNull(); }); + + await waitFor(async () => { + const items = await screen.queryAllByText(/VoiceOver Bot/); + expect(items).toHaveLength(1); + }); }); it('removes tester correctly and calls removeTester mutation', async () => { @@ -256,7 +341,10 @@ describe('AssignTesterDropdown', () => { ]; render( - + ); diff --git a/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js index 34f34a85c..aaca65dfd 100644 --- a/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js @@ -31,6 +31,7 @@ export default ( ats: [ { id: '1', + key: 'jaws', name: 'JAWS', atVersions: [ { @@ -42,10 +43,12 @@ export default ( browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' } ], @@ -54,6 +57,7 @@ export default ( }, { id: '2', + key: 'nvda', name: 'NVDA', atVersions: [ { @@ -65,10 +69,12 @@ export default ( browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' } ], @@ -77,6 +83,7 @@ export default ( }, { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS', atVersions: [ { @@ -88,14 +95,17 @@ export default ( browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '3', + key: 'safari_macos', name: 'Safari' } ], @@ -401,10 +411,12 @@ export default ( isFinal: false, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -568,10 +580,12 @@ export default ( isFinal: false, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -1071,10 +1085,12 @@ export default ( isFinal: false, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -1406,10 +1422,12 @@ export default ( isFinal: true, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '3', + key: 'safari', name: 'Safari' }, issues: [], @@ -1555,10 +1573,12 @@ export default ( isFinal: false, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -1644,10 +1664,12 @@ export default ( isFinal: false, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -1753,10 +1775,12 @@ export default ( isFinal: false, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -1842,10 +1866,12 @@ export default ( isFinal: false, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -1931,10 +1957,12 @@ export default ( isFinal: true, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -2050,10 +2078,12 @@ export default ( isFinal: false, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -2139,10 +2169,12 @@ export default ( isFinal: true, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -2288,10 +2320,12 @@ export default ( isFinal: true, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '3', + key: 'safari', name: 'Safari' }, issues: [], @@ -2422,10 +2456,12 @@ export default ( isFinal: false, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -2525,10 +2561,12 @@ export default ( isFinal: false, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -2586,10 +2624,12 @@ export default ( isFinal: true, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '3', + key: 'safari', name: 'Safari' }, issues: [], @@ -2735,10 +2775,12 @@ export default ( isFinal: true, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -2824,10 +2866,12 @@ export default ( isFinal: true, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -2942,10 +2986,12 @@ export default ( isFinal: false, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -3248,10 +3294,12 @@ export default ( isFinal: false, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -3337,10 +3385,12 @@ export default ( isFinal: false, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -3426,10 +3476,12 @@ export default ( isFinal: true, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -3545,10 +3597,12 @@ export default ( isFinal: false, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -3634,10 +3688,12 @@ export default ( isFinal: true, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], @@ -3917,10 +3973,12 @@ export default ( isFinal: false, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -4035,10 +4093,12 @@ export default ( isFinal: false, at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' }, issues: [], diff --git a/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js b/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js index 3dee6df1b..54b84d016 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js @@ -36,10 +36,12 @@ export const mockedTestPlanVersion = { markedFinalAt: null, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, issues: [], @@ -309,6 +311,7 @@ export default ( ats: [ { id: '1', + key: 'jaws', name: 'JAWS', atVersions: [ { @@ -320,10 +323,12 @@ export default ( browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' } ], @@ -332,6 +337,7 @@ export default ( }, { id: '2', + key: 'nvda', name: 'NVDA', atVersions: [ { @@ -343,10 +349,12 @@ export default ( browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' } ], @@ -355,6 +363,7 @@ export default ( }, { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS', atVersions: [ { @@ -366,14 +375,17 @@ export default ( browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '3', + key: 'safari', name: 'Safari' } ], @@ -405,10 +417,14 @@ export default ( initiatedByAutomation: true }, at: { - id: '1' + id: '1', + key: 'jaws', + name: 'JAWS' }, browser: { - id: '2' + id: '2', + key: 'firefox', + name: 'Firefox' } } ] diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js index 71e44308a..98ccbfc20 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js @@ -18,19 +18,22 @@ export default testQueuePageQuery => [ id: '1', username: 'foo-bar', roles: ['ADMIN', 'TESTER'], - isBot: false + isBot: false, + ats: [] }, { id: '4', username: 'bar-foo', roles: ['TESTER'], - isBot: false + isBot: false, + ats: [] }, { id: '5', username: 'boo-far', roles: ['TESTER'], - isBot: false + isBot: false, + ats: [] } ], testPlanVersions: [], diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js index 53008087a..0625ca224 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js @@ -15,6 +15,7 @@ export default testQueuePageQuery => [ { id: '1', name: 'JAWS', + key: 'jaws', atVersions: [ { id: '1', @@ -25,14 +26,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '3', + key: 'safari', name: 'Safari' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '2', + key: 'chrome', name: 'Chrome' } ], @@ -55,6 +59,7 @@ export default testQueuePageQuery => [ }, { id: '2', + key: 'nvda', name: 'NVDA', atVersions: [ { @@ -86,14 +91,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '3', + key: 'safari', name: 'Safari' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '2', + key: 'chrome', name: 'Chrome' } ], @@ -116,6 +124,7 @@ export default testQueuePageQuery => [ }, { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS', atVersions: [ { @@ -127,14 +136,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '3', + key: 'safari', name: 'Safari' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '2', + key: 'chrome', name: 'Chrome' } ], @@ -159,14 +171,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '3', + key: 'safari_macos', name: 'Safari' } ], @@ -175,19 +190,22 @@ export default testQueuePageQuery => [ id: '1', username: 'esmeralda-baggins', roles: ['TESTER', 'ADMIN'], - isBot: false + isBot: false, + ats: [] }, { id: '2', username: 'tom-proudfeet', roles: ['TESTER'], - isBot: false + isBot: false, + ats: [] }, { id: '101', username: 'alflennik', roles: ['TESTER', 'ADMIN'], - isBot: false + isBot: false, + ats: [] } ], testPlanVersions: [ @@ -235,8 +253,8 @@ export default testQueuePageQuery => [ conflictsLength: 0, runnableTestsLength: 17, markedFinalAt: null, - at: { id: '1', name: 'JAWS' }, - browser: { id: '2', name: 'Chrome' }, + at: { id: '1', name: 'JAWS', key: 'jaws' }, + browser: { id: '2', name: 'Chrome', key: 'chrome' }, testPlanVersion: { id: '1', title: 'Checkbox Example (Two State)', @@ -265,8 +283,16 @@ export default testQueuePageQuery => [ conflictsLength: 0, runnableTestsLength: 17, markedFinalAt: null, - at: { id: '3', name: 'VoiceOver for macOS' }, - browser: { id: '3', name: 'Safari' }, + at: { + id: '3', + name: 'VoiceOver for macOS', + key: 'voiceover_macos' + }, + browser: { + id: '3', + name: 'Safari', + key: 'safari_macos' + }, testPlanVersion: { id: '1', title: 'Checkbox Example (Two State)', @@ -295,8 +321,8 @@ export default testQueuePageQuery => [ conflictsLength: 3, runnableTestsLength: 17, markedFinalAt: null, - at: { id: '2', name: 'NVDA' }, - browser: { id: '1', name: 'Firefox' }, + at: { id: '2', name: 'NVDA', key: 'nvda' }, + browser: { id: '1', name: 'Firefox', key: 'firefox' }, testPlanVersion: { id: '1', title: 'Checkbox Example (Two State)', diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js index 2aed220dc..06dfcc0f6 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js @@ -12,10 +12,12 @@ export default (testPlanReportAtBrowserQuery, existingTestPlanReportsQuery) => [ id: '3', at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' } } @@ -35,10 +37,12 @@ export default (testPlanReportAtBrowserQuery, existingTestPlanReportsQuery) => [ id: '2', at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' } } @@ -58,10 +62,12 @@ export default (testPlanReportAtBrowserQuery, existingTestPlanReportsQuery) => [ id: '1', at: { id: '1', + key: 'jaws', name: 'JAWS' }, browser: { id: '2', + key: 'chrome', name: 'Chrome' } } @@ -89,10 +95,12 @@ export default (testPlanReportAtBrowserQuery, existingTestPlanReportsQuery) => [ initiatedByAutomation: true }, at: { - id: '1' + id: '1', + key: 'jaws' }, browser: { - id: '2' + id: '2', + key: 'chrome' } } ] diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js index 266235ed0..8b600c669 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js @@ -19,6 +19,7 @@ export default testQueuePageQuery => [ username: 'foo-bar', roles: ['ADMIN', 'TESTER'], isBot: false, + ats: [], __typename: 'User' }, { @@ -26,6 +27,7 @@ export default testQueuePageQuery => [ username: 'bar-foo', roles: ['TESTER'], isBot: false, + ats: [], __typename: 'User' }, { @@ -33,6 +35,7 @@ export default testQueuePageQuery => [ username: 'boo-far', roles: ['TESTER'], isBot: false, + ats: [], __typename: 'User' } ], diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js index 7e621452c..dcf29263d 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js @@ -14,6 +14,7 @@ export default testQueuePageQuery => [ ats: [ { id: '1', + key: 'jaws', name: 'JAWS', atVersions: [ { @@ -25,14 +26,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '3', + key: 'safari', name: 'Safari' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '2', + key: 'chrome', name: 'Chrome' } ], @@ -55,6 +59,7 @@ export default testQueuePageQuery => [ }, { id: '2', + key: 'nvda', name: 'NVDA', atVersions: [ { @@ -86,14 +91,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '3', + key: 'safari', name: 'Safari' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '2', + key: 'chrome', name: 'Chrome' } ], @@ -116,6 +124,7 @@ export default testQueuePageQuery => [ }, { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS', atVersions: [ { @@ -127,14 +136,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '3', + key: 'safari', name: 'Safari' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '2', + key: 'chrome', name: 'Chrome' } ], @@ -159,14 +171,17 @@ export default testQueuePageQuery => [ browsers: [ { id: '2', + key: 'chrome', name: 'Chrome' }, { id: '1', + key: 'firefox', name: 'Firefox' }, { id: '3', + key: 'safari_macos', name: 'Safari' } ], @@ -175,19 +190,22 @@ export default testQueuePageQuery => [ id: '1', username: 'foo-bar', roles: ['ADMIN', 'TESTER'], - isBot: false + isBot: false, + ats: [] }, { id: '4', username: 'bar-foo', roles: ['TESTER'], - isBot: false + isBot: false, + ats: [] }, { id: '5', username: 'boo-far', roles: ['TESTER'], - isBot: false + isBot: false, + ats: [] } ], testPlanVersions: [ @@ -237,10 +255,12 @@ export default testQueuePageQuery => [ markedFinalAt: null, at: { id: '2', + key: 'nvda', name: 'NVDA' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, testPlanVersion: { @@ -285,10 +305,12 @@ export default testQueuePageQuery => [ markedFinalAt: null, at: { id: '2', + key: 'jaws', name: 'JAWS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, testPlanVersion: { @@ -323,10 +345,12 @@ export default testQueuePageQuery => [ markedFinalAt: null, at: { id: '3', + key: 'voiceover_macos', name: 'VoiceOver for macOS' }, browser: { id: '1', + key: 'firefox', name: 'Firefox' }, testPlanVersion: { diff --git a/client/utils/automation.js b/client/utils/automation.js index 4406116ed..71d3d978e 100644 --- a/client/utils/automation.js +++ b/client/utils/automation.js @@ -2,15 +2,31 @@ export const isSupportedByResponseCollector = ctx => { if (!ctx || !ctx.at || !ctx.browser) { return false; } + const { + at: { key: atKey }, + browser: { key: browserKey } + } = ctx; return ( - ctx.at.name === 'NVDA' && - (ctx.browser.name === 'Chrome' || ctx.browser.name === 'Firefox') + (atKey === 'nvda' && + (browserKey === 'chrome' || browserKey === 'firefox')) || + (atKey === 'voiceover_macos' && browserKey === 'safari_macos') ); }; -// TODO: Stub, support for more bot users should be added +/** + * @param {} [at] + * @param {} [browser] + * + * @returns {string|undefined} + */ export const getBotUsernameFromAtBrowser = (at, browser) => { - if (at?.name === 'NVDA' && browser?.name === 'Chrome') { + if ( + at?.key === 'nvda' && + (browser?.key === 'chrome' || browser?.key === 'firefox') + ) { return 'NVDA Bot'; } + if (at?.key === 'voiceover_macos' && browser?.key === 'safari_macos') { + return 'VoiceOver Bot'; + } }; diff --git a/server/graphql-schema.js b/server/graphql-schema.js index 2085d08bd..6d16220c4 100644 --- a/server/graphql-schema.js +++ b/server/graphql-schema.js @@ -137,6 +137,10 @@ const graphqlSchema = gql` """ name: String! """ + Consistent key name for browser like "chrome" or "safari_macos" + """ + key: String! + """ A fully-qualified version like "99.0.4844.84" """ browserVersions: [BrowserVersion]! @@ -191,6 +195,13 @@ const graphqlSchema = gql` Human-readable name for the AT, such as "NVDA". """ name: String! + """ + Consistent key value for lookups. + """ + key: String! + """ + Recorded version numbers + """ atVersions: [AtVersion]! """ The browsers which can run the At, for example, Safari can run VoiceOver but not Jaws because Jaws is Windows only. diff --git a/server/models/At.js b/server/models/At.js index 08f167d2c..e4d50617b 100644 --- a/server/models/At.js +++ b/server/models/At.js @@ -13,6 +13,10 @@ module.exports = function (sequelize, DataTypes) { name: { type: DataTypes.TEXT, allowNull: false + }, + key: { + type: DataTypes.TEXT, + allowNull: false } }, { diff --git a/server/models/Browser.js b/server/models/Browser.js index 4580893a6..e714776bf 100644 --- a/server/models/Browser.js +++ b/server/models/Browser.js @@ -13,6 +13,10 @@ module.exports = function (sequelize, DataTypes) { name: { type: DataTypes.TEXT, allowNull: false + }, + key: { + type: DataTypes.TEXT, + allowNull: false } }, { diff --git a/server/models/services/AtService.js b/server/models/services/AtService.js index 9ae9aecc4..27508ad7f 100644 --- a/server/models/services/AtService.js +++ b/server/models/services/AtService.js @@ -116,14 +116,14 @@ const getAts = async ({ * @returns {Promise<*>} */ const createAt = async ({ - values: { name }, + values: { name, key }, atAttributes = AT_ATTRIBUTES, atVersionAttributes = AT_VERSION_ATTRIBUTES, browserAttributes = BROWSER_ATTRIBUTES, transaction }) => { const atResult = await ModelService.create(At, { - values: { name }, + values: { name, key }, transaction }); const { id } = atResult; diff --git a/server/models/services/BrowserService.js b/server/models/services/BrowserService.js index bae02631d..d7ed7fb16 100644 --- a/server/models/services/BrowserService.js +++ b/server/models/services/BrowserService.js @@ -116,14 +116,14 @@ const getBrowsers = async ({ * @returns {Promise<*>} */ const createBrowser = async ({ - values: { name }, + values: { name, key }, browserAttributes = BROWSER_ATTRIBUTES, browserVersionAttributes = BROWSER_VERSION_ATTRIBUTES, atAttributes = AT_ATTRIBUTES, transaction }) => { const browserResult = await ModelService.create(Browser, { - values: { name }, + values: { name, key }, transaction }); const { id } = browserResult; diff --git a/server/models/services/CollectionJobService.js b/server/models/services/CollectionJobService.js index bbe756bd9..a31eeb8f6 100644 --- a/server/models/services/CollectionJobService.js +++ b/server/models/services/CollectionJobService.js @@ -17,7 +17,6 @@ const { createTestPlanRun, removeTestPlanRunById } = require('./TestPlanRunService'); -const responseCollectionUser = require('../../util/responseCollectionUser'); const { getTestPlanReportById } = require('./TestPlanReportService'); const { HttpQueryError } = require('apollo-server-core'); const { default: axios } = require('axios'); @@ -27,6 +26,7 @@ const { } = require('../../services/GithubWorkflowService'); const runnableTestsResolver = require('../../resolvers/TestPlanReport/runnableTestsResolver'); const getGraphQLContext = require('../../graphql-context'); +const { getBotUserByAtId } = require('./UserService'); const axiosConfig = { headers: { @@ -188,7 +188,11 @@ const collectionJobTestStatusAssociation = /** * @param {object} options - * @param {object} options.values - CollectionJob to be created + * @param {object} options.values + * @param {string} options.values.status - Status of CollectionJob to be created + * @param {number} options.values.testerUserId - ID of the Tester to which the CollectionJob should be assigned + * @param {object} options.values.testPlanReportId - ID of the TestPlan with which the CollectionJob should be associated + * @param {object} [options.values.testPlanRun] - TestPlan with wich the CollectionJob should be associated (if not provided, a new TestPlan will be created) * @param {string[]} options.collectionJobAttributes - CollectionJob attributes to be returned in the result * @param {string[]} options.collectionJobTestStatusAttributes - CollectionJobTestStatus attributes to be returned in the result * @param {string[]} options.testPlanReportAttributes - TestPlanReport attributes to be returned in the result @@ -203,6 +207,7 @@ const collectionJobTestStatusAssociation = const createCollectionJob = async ({ values: { status = COLLECTION_JOB_STATUS.QUEUED, + testerUserId, testPlanRun, testPlanReportId }, @@ -220,7 +225,7 @@ const createCollectionJob = async ({ if (!testPlanRun) { testPlanRun = await createTestPlanRun({ values: { - testerUserId: responseCollectionUser.id, + testerUserId, testPlanReportId: testPlanReportId, isAutomated: true }, @@ -410,7 +415,13 @@ const triggerWorkflow = async (job, testIds, { transaction }) => { ); } } catch (error) { + console.error(error); // TODO: What to do with the actual error (could be nice to have an additional "string" status field?) + await updateCollectionJobTestStatusByQuery({ + where: { collectionJobId: job.id }, + values: { status: COLLECTION_JOB_STATUS.ERROR }, + transaction + }); return updateCollectionJobById({ id: job.id, values: { status: COLLECTION_JOB_STATUS.ERROR }, @@ -538,6 +549,14 @@ const scheduleCollectionJob = async ( const tests = await runnableTestsResolver(report, null, context); const { directory } = report.testPlanVersion.testPlan; const { gitSha } = report.testPlanVersion; + const testerUser = await getBotUserByAtId({ + atId: report.at.id, + transaction + }); + if (!testerUser) { + throw new Error(`No bot user found for AT ${report.at.name}`); + } + const testerUserId = testerUser.id; if (!tests || tests.length === 0) { throw new Error( @@ -560,6 +579,7 @@ const scheduleCollectionJob = async ( const job = await createCollectionJob({ values: { status: COLLECTION_JOB_STATUS.QUEUED, + testerUserId, testPlanReportId }, transaction diff --git a/server/models/services/UserService.js b/server/models/services/UserService.js index 552c65a9f..98099822c 100644 --- a/server/models/services/UserService.js +++ b/server/models/services/UserService.js @@ -148,6 +148,27 @@ const getUsers = async ({ }); }; +/** + */ +const getBotUserByAtId = async ({ + atId, + userAttributes = USER_ATTRIBUTES, + atAttributes = AT_ATTRIBUTES, + transaction +}) => { + return ModelService.getByQuery(User, { + where: { isBot: true }, + attributes: userAttributes, + include: [ + { + ...atAssociation(atAttributes), + where: { id: atId } + } + ], + transaction + }); +}; + /** * @param {object} options * @param {string|any} options.search - use this to combine with {@param filter} to be passed to Sequelize's where clause @@ -464,6 +485,7 @@ module.exports = { getUserById, getUserByUsername, getUsers, + getBotUserByAtId, getUserRoles, getUserAts, createUser, diff --git a/server/resolvers/User/atsResolver.js b/server/resolvers/User/atsResolver.js index 95afd92ba..fe20ca1bb 100644 --- a/server/resolvers/User/atsResolver.js +++ b/server/resolvers/User/atsResolver.js @@ -1,7 +1,9 @@ const { getUserById } = require('../../models/services/UserService'); -const atsResolver = async (_, __, context) => { - const { user, transaction } = context; +const atsResolver = async (user, __, context) => { + const { transaction } = context; + + if (user.ats) return user.ats; const { ats } = await getUserById({ id: user.id, transaction }); diff --git a/server/seeders/20231218191524-addNVDABot.js b/server/seeders/20231218191524-addNVDABot.js index 52f60747d..017f8d5cf 100644 --- a/server/seeders/20231218191524-addNVDABot.js +++ b/server/seeders/20231218191524-addNVDABot.js @@ -1,6 +1,6 @@ 'use strict'; -const responseCollectionUser = require('../util/responseCollectionUser'); +const responseCollectionUserIDs = require('../util/responseCollectionUserIDs'); module.exports = { async up(queryInterface) { @@ -8,9 +8,9 @@ module.exports = { 'User', [ { - id: responseCollectionUser.id, // Specified ID for NVDA Bot - username: responseCollectionUser.username, - isBot: responseCollectionUser.isBot, + id: responseCollectionUserIDs['NVDA Bot'], + username: 'NVDA Bot', + isBot: true, createdAt: new Date(), updatedAt: new Date() } @@ -24,11 +24,14 @@ module.exports = { roleName: 'TESTER' } ]); + + // note to someone copying this seeder to add JAWS, we now need to also + // link to the UserAts table - see 20240520125142-addBotAts.js }, async down(queryInterface) { await queryInterface.bulkDelete('User', { - id: responseCollectionUser.id + id: responseCollectionUserIDs['NVDA Bot'] }); } }; diff --git a/server/seeders/20240516191524-addVoiceOverBot.js b/server/seeders/20240516191524-addVoiceOverBot.js new file mode 100644 index 000000000..d0dd8d220 --- /dev/null +++ b/server/seeders/20240516191524-addVoiceOverBot.js @@ -0,0 +1,37 @@ +'use strict'; + +const responseCollectionUserIDs = require('../util/responseCollectionUserIDs'); + +module.exports = { + async up(queryInterface) { + const user = await queryInterface.bulkInsert( + 'User', + [ + { + id: responseCollectionUserIDs['VoiceOver Bot'], + username: 'VoiceOver Bot', + isBot: true, + createdAt: new Date(), + updatedAt: new Date() + } + ], + { returning: true } + ); + + await queryInterface.bulkInsert('UserRoles', [ + { + userId: user[0].id, + roleName: 'TESTER' + } + ]); + + // note to someone copying this seeder to add JAWS, we now need to also + // link to the UserAts table - see 20240520125142-addBotAts.js + }, + + async down(queryInterface) { + await queryInterface.bulkDelete('User', { + id: responseCollectionUserIDs['VoiceOver Bot'] + }); + } +}; diff --git a/server/seeders/20240520125142-addBotAts.js b/server/seeders/20240520125142-addBotAts.js new file mode 100644 index 000000000..ed51f10a7 --- /dev/null +++ b/server/seeders/20240520125142-addBotAts.js @@ -0,0 +1,38 @@ +'use strict'; + +const responseCollectionUserIDs = require('../util/responseCollectionUserIDs'); + +module.exports = { + async up(queryInterface) { + await queryInterface.sequelize.query(` + INSERT INTO "UserAts" + SELECT + ${responseCollectionUserIDs['NVDA Bot']} AS userId, + id AS atId + FROM "At" + WHERE + "At"."key" = 'nvda' + ; + `); + await queryInterface.sequelize.query(` + INSERT INTO "UserAts" + SELECT + ${responseCollectionUserIDs['VoiceOver Bot']} AS userId, + id AS atId + FROM "At" + WHERE + "At"."key" = 'voiceover_macos' + ; + `); + }, + + async down(queryInterface) { + await queryInterface.sequelize.query(` + DELETE FROM "UserAts" + WHERE "UserAts"."userId" IN ( + ${responseCollectionUserIDs['NVDA Bot']}, + ${responseCollectionUserIDs['VoiceOver Bot']} + ); + `); + } +}; diff --git a/server/services/GithubWorkflowService.js b/server/services/GithubWorkflowService.js index 2fe571563..f28f31f13 100644 --- a/server/services/GithubWorkflowService.js +++ b/server/services/GithubWorkflowService.js @@ -21,7 +21,6 @@ const ALGORITHM = 'RS256'; // > the workflow file is on the default branch. // // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch -const WORKFLOW_FILE_NAME = 'nvda-test.yml'; const WORKFLOW_REPO = 'bocoup/aria-at-gh-actions-helper'; // Generated from the GitHub.com UI @@ -126,19 +125,32 @@ const createGithubWorkflow = async ({ job, directory, gitSha }) => { jsonWebToken, GITHUB_APP_INSTALLATION_ID ); + + const atKey = job.testPlanRun.testPlanReport.at.key; + const workflowFilename = { + nvda: 'nvda-test.yml', + voiceover_macos: 'voiceover-test.yml' + }[atKey]; + + if (!workflowFilename) { + throw new Error(`Unsupported AT workflow for ${atKey}`); + } + const browser = job.testPlanRun.testPlanReport.browser.name.toLowerCase(); const inputs = { callback_url: `https://${callbackUrlHostname}/api/jobs/${job.id}/test/:testRowNumber`, status_url: `https://${callbackUrlHostname}/api/jobs/${job.id}`, callback_header: `x-automation-secret:${process.env.AUTOMATION_SCHEDULER_SECRET}`, work_dir: `tests/${directory}`, - test_pattern: '{reference/**,test-*-nvda.*}', - aria_at_ref: gitSha, - browser + aria_at_ref: gitSha }; + if (atKey === 'nvda') { + inputs.test_pattern = '{reference/**,test-*-nvda.*}'; + inputs.browser = browser; + } const axiosConfig = { method: 'POST', - url: `https://api.github.com/repos/${WORKFLOW_REPO}/actions/workflows/${WORKFLOW_FILE_NAME}/dispatches`, + url: `https://api.github.com/repos/${WORKFLOW_REPO}/actions/workflows/${workflowFilename}/dispatches`, headers: { Accept: 'application/vnd.github+json', @@ -154,7 +166,11 @@ const createGithubWorkflow = async ({ job, directory, gitSha }) => { }; const response = await axios(axiosConfig); if (response.status < 200 || response.status >= 300) { - throw new Error(response.data ?? 'Unable to initiate workflow'); + throw new Error( + response.data + ? JSON.stringify(response.data) + : 'Unable to initiate workflow' + ); } return true; diff --git a/server/tests/integration/graphql.test.js b/server/tests/integration/graphql.test.js index cfc0ffbe6..d6d9744fa 100644 --- a/server/tests/integration/graphql.test.js +++ b/server/tests/integration/graphql.test.js @@ -194,6 +194,7 @@ describe('graphql', () => { browsers { __typename id + key name ats { __typename @@ -219,6 +220,7 @@ describe('graphql', () => { ats { __typename id + key name browsers { __typename diff --git a/server/tests/models/services/AtService.test.js b/server/tests/models/services/AtService.test.js index 74fe04d1b..1a59fe973 100644 --- a/server/tests/models/services/AtService.test.js +++ b/server/tests/models/services/AtService.test.js @@ -97,7 +97,7 @@ describe('AtModel Data Checks', () => { // A2 - create at const at = await AtService.createAt({ - values: { name: _name }, + values: { name: _name, key: _name }, transaction }); const { id, name } = at; @@ -123,7 +123,7 @@ describe('AtModel Data Checks', () => { // A2 - create at const at = await AtService.createAt({ - values: { name: _name }, + values: { name: _name, key: _name }, transaction }); const { id, name } = at; diff --git a/server/tests/models/services/BrowserService.test.js b/server/tests/models/services/BrowserService.test.js index b2024a1c2..f1b325815 100644 --- a/server/tests/models/services/BrowserService.test.js +++ b/server/tests/models/services/BrowserService.test.js @@ -109,7 +109,7 @@ describe('BrowserModel Data Checks', () => { // A2 const browser = await BrowserService.createBrowser({ - values: { name: _name }, + values: { name: _name, key: _name }, transaction }); const { id, name } = browser; @@ -138,7 +138,7 @@ describe('BrowserModel Data Checks', () => { // A2 const browser = await BrowserService.createBrowser({ - values: { name: _name }, + values: { name: _name, key: _name }, transaction }); const { id, name } = browser; diff --git a/server/tests/models/services/UserService.test.js b/server/tests/models/services/UserService.test.js index 428ca95f3..b83c45dac 100644 --- a/server/tests/models/services/UserService.test.js +++ b/server/tests/models/services/UserService.test.js @@ -3,6 +3,7 @@ const { sequelize } = require('../../../models'); const UserService = require('../../../models/services/UserService'); const randomStringGenerator = require('../../util/random-character-generator'); const dbCleaner = require('../../util/db-cleaner'); +const responseCollectionUserIDs = require('../../../util/responseCollectionUserIDs'); describe('UserModel Data Checks', () => { afterAll(async () => { @@ -334,4 +335,16 @@ describe('UserModel Data Checks', () => { expect(user1Ats[0].userId).toBe(_userId); expect(user1Ats[0].atId).toBeTruthy(); }); + + describe('getBotUserByAtId', () => { + it('should find nvda bot user', async () => { + const user = await UserService.getBotUserByAtId({ + atId: 2, + transaction: false + }); + expect(user).toBeDefined(); + expect(user.id).toEqual(responseCollectionUserIDs['NVDA Bot']); + expect(user.username).toEqual('NVDA Bot'); + }); + }); }); diff --git a/server/util/responseCollectionUser.js b/server/util/responseCollectionUser.js deleted file mode 100644 index e1babb3f2..000000000 --- a/server/util/responseCollectionUser.js +++ /dev/null @@ -1,8 +0,0 @@ -// TODO: Defaults to NVDA, offer AT-specific bot once support is added -const responseCollectionUser = { - username: 'NVDA Bot', - isBot: true, - id: 9999 -}; - -module.exports = responseCollectionUser; diff --git a/server/util/responseCollectionUserIDs.js b/server/util/responseCollectionUserIDs.js new file mode 100644 index 000000000..3d0cc3a1a --- /dev/null +++ b/server/util/responseCollectionUserIDs.js @@ -0,0 +1,4 @@ +module.exports = { + 'NVDA Bot': 9999, + 'VoiceOver Bot': 9998 +};