-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow End-to-End Testing as an Admin or Tester (#908)
* Initial smoke test before testing in CI * Make adjustments for CI * Testing if it is just slow * Comment out new test * Reenable test * Try headless chrome * Try running just one test * Add logging * Add more logging * Found potential environmental issue * Try fixing database connection * Try turning off sandbox mode * Try using a package to kill the server * Run full test suite instead of just one test * Some final polish * PR polish * Enable sign-in in e2e tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Work on fixing tests * Carry over changes from main * Add todo to list of todos * PR feedback * Merge config * Use services.deprecated to fix test * Fix sandbox config
- Loading branch information
Showing
19 changed files
with
382 additions
and
336 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,142 +1,88 @@ | ||
const puppeteer = require('puppeteer'); | ||
const path = require('path'); | ||
const spawn = require('cross-spawn'); | ||
const treeKill = require('tree-kill'); | ||
import getPage, { setup, teardown } from './util/getPage'; | ||
|
||
/* | ||
End-to-End Testing TODO: | ||
- The server start and close functions should be handled in one place by | ||
Jest's setup and teardown scripts. | ||
- There needs to be a utility function to enable common tasks like getting a | ||
fresh end-to-end page. | ||
- End-to-end testing should support signing in with different roles, A.K.A. as | ||
an admin, tester or vendor. | ||
- It should be possible to reset the database to a predictable state after each | ||
test, ideally in such a way that concurrency remains possible. See the POC | ||
here: https://github.com/w3c/aria-at-app/pull/895 | ||
- Add section to docs for end-to-end testing | ||
*/ | ||
|
||
const PORT = 8033; | ||
const CLIENT_PORT = 3033; | ||
const AUTOMATION_SCHEDULER_PORT = 8833; | ||
|
||
const startServer = async serverOrClient => { | ||
return new Promise(resolve => { | ||
const server = spawn('yarn', ['workspace', serverOrClient, 'dev'], { | ||
cwd: path.resolve(__dirname, '../../'), | ||
env: { | ||
PATH: process.env.PATH, | ||
PORT, | ||
CLIENT_PORT: 3033, | ||
AUTOMATION_SCHEDULER_PORT: 8833, | ||
API_SERVER: `http://localhost:${PORT}`, | ||
APP_SERVER: `http://localhost:${CLIENT_PORT}`, | ||
AUTOMATION_SCHEDULER_URL: `http://localhost:${AUTOMATION_SCHEDULER_PORT}`, | ||
PGDATABASE: 'aria_at_report_test', | ||
PGPORT: 5432, | ||
ENVIRONMENT: 'test' | ||
} | ||
}); | ||
|
||
const killServer = async () => { | ||
await new Promise((resolve, reject) => { | ||
treeKill(server.pid, error => { | ||
if (error) return reject(error); | ||
resolve(); | ||
}); | ||
}); | ||
}; | ||
describe('smoke test', () => { | ||
beforeAll(async () => { | ||
await setup(); | ||
}, 30000); | ||
|
||
server.stdout.on('data', data => { | ||
const output = data.toString(); | ||
console.info(output); // eslint-disable-line no-console | ||
afterAll(async () => { | ||
await teardown(); | ||
}, 30000); | ||
|
||
if ( | ||
(serverOrClient === 'server' && | ||
output.includes(`Listening on ${PORT}`)) || | ||
(serverOrClient === 'client' && | ||
output.includes('compiled successfully')) | ||
) { | ||
resolve({ close: killServer }); | ||
} | ||
}); | ||
it('can sign in as admin, tester, vendor, or logged out', async () => { | ||
await Promise.all([ | ||
getPage({ role: 'admin', url: '/test-queue' }, async page => { | ||
// Only admins can remove rows from the test queue | ||
await page.waitForSelector('td.actions ::-p-text(Remove)'); | ||
}), | ||
|
||
server.stderr.on('data', data => { | ||
const output = data.toString(); | ||
console.info(output); // eslint-disable-line no-console | ||
}); | ||
}); | ||
}; | ||
getPage({ role: 'tester', url: '/test-queue' }, async page => { | ||
// Testers can assign themselves | ||
await page.waitForSelector('table ::-p-text(Assign Yourself)'); | ||
const adminOnlyRemoveButton = await page.$( | ||
'td.actions ::-p-text(Remove)' | ||
); | ||
expect(adminOnlyRemoveButton).toBe(null); | ||
}), | ||
|
||
describe('smoke test', () => { | ||
let browser; | ||
let backendServer; | ||
let clientServer; | ||
getPage( | ||
{ role: 'vendor', url: '/test-queue' }, | ||
async (page, { baseUrl }) => { | ||
// Vendors get the same test queue as signed-out users | ||
await page.waitForSelector( | ||
'td.actions ::-p-text(View tests)' | ||
); | ||
// Unlike signed-out users, they will get tables on this page | ||
await page.goto(`${baseUrl}/candidate-review`); | ||
await page.waitForSelector('table'); | ||
} | ||
), | ||
|
||
beforeAll(async () => { | ||
// eslint-disable-next-line no-console | ||
console.info( | ||
'Starting dev servers. This is required for end-to-end testing' | ||
); | ||
[clientServer, backendServer] = await Promise.all([ | ||
startServer('client'), | ||
startServer('server') | ||
getPage({ role: false, url: '/test-queue' }, async page => { | ||
// Signed-out users can only view tests, not run them | ||
await page.waitForSelector('td.actions ::-p-text(View tests)'); | ||
}) | ||
]); | ||
|
||
browser = await puppeteer.launch({ | ||
headless: 'new', | ||
args: ['--no-sandbox'] // Required for GitHub environment | ||
}); | ||
const [extraBlankPage] = await browser.pages(); | ||
extraBlankPage.close(); | ||
}, 60000); | ||
|
||
afterAll(async () => { | ||
await Promise.all([backendServer.close(), clientServer.close()]); | ||
|
||
// Browser might not be defined, if it failed to start | ||
if (browser) await browser.close(); | ||
}, 60000); | ||
}, 10000); | ||
|
||
it('loads various pages without crashing', async () => { | ||
let homeH1; | ||
let reportsH1; | ||
let dataManagementH1; | ||
|
||
await Promise.all([ | ||
(async () => { | ||
const page = await browser.newPage(); | ||
await page.goto(`http://localhost:${CLIENT_PORT}/`); | ||
getPage({ role: false, url: '/' }, async page => { | ||
await page.waitForSelector('h1'); | ||
const h1Handle = await page.waitForSelector('h1'); | ||
homeH1 = await h1Handle.evaluate(h1 => h1.innerText); | ||
})(), | ||
(async () => { | ||
const page = await browser.newPage(); | ||
await page.goto(`http://localhost:${CLIENT_PORT}/reports`); | ||
const h1Text = await h1Handle.evaluate(h1 => h1.innerText); | ||
expect(h1Text).toBe( | ||
'Enabling Interoperability for Assistive Technology Users' | ||
); | ||
}), | ||
getPage({ role: false, url: '/reports' }, async page => { | ||
// Wait for an h2 because an h1 will show while the page is | ||
// still loading | ||
await page.waitForSelector('h2'); | ||
const h1Handle = await page.waitForSelector('h1'); | ||
reportsH1 = await h1Handle.evaluate(h1 => h1.innerText); | ||
})(), | ||
(async () => { | ||
const page = await browser.newPage(); | ||
await page.goto( | ||
`http://localhost:${CLIENT_PORT}/data-management` | ||
const h1Text = await h1Handle.evaluate(h1 => h1.innerText); | ||
expect(h1Text).toBe( | ||
'Assistive Technology Interoperability Reports' | ||
); | ||
}), | ||
getPage({ role: false, url: '/data-management' }, async page => { | ||
// Wait for an h2 because an h1 will show while the page is | ||
// still loading | ||
await page.waitForSelector('h2'); | ||
const h1Handle = await page.waitForSelector('h1'); | ||
dataManagementH1 = await h1Handle.evaluate(h1 => h1.innerText); | ||
})() | ||
const h1Text = await h1Handle.evaluate(h1 => h1.innerText); | ||
expect(h1Text).toBe('Data Management'); | ||
}) | ||
]); | ||
|
||
expect(homeH1).toBe( | ||
'Enabling Interoperability for Assistive Technology Users' | ||
); | ||
expect(reportsH1).toBe('Assistive Technology Interoperability Reports'); | ||
expect(dataManagementH1).toBe('Data Management'); | ||
}, 60000); | ||
}, 10000); | ||
}); |
Oops, something went wrong.