Skip to content

Commit b997a1d

Browse files
Merge pull request #16 from oxctl/AB#108653
AB#108653 added jsdoc
2 parents b26a781 + 410de62 commit b997a1d

1 file changed

Lines changed: 73 additions & 13 deletions

File tree

src/testUtils.js

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
import { expect } from '@playwright/test'
22

3-
// Return a valid URL of the test course or account - assertVariables.js will
4-
// ensure these env vars exist and are normalised.
5-
export const TEST_URL = process.env.CANVAS_HOST + "/" + process.env.TEST_PATH
3+
/**
4+
* Normalised test URL built from `CANVAS_HOST` and `TEST_PATH`.
5+
* `src/setup/assertVariables.js` ensures these env vars exist and are normalised.
6+
* @type {string}
7+
*/
8+
export const TEST_URL = process.env.CANVAS_HOST + '/' + process.env.TEST_PATH
69

710

11+
/**
12+
* Perform an LTI login by requesting a session token and navigating the page
13+
* to the returned session URL.
14+
* @param {import('@playwright/test').APIRequestContext} request - Playwright request context
15+
* @param {import('@playwright/test').Page} page - Playwright page to navigate
16+
* @param {string} host - Canvas host (base URL)
17+
* @param {string} token - OAuth bearer token
18+
* @returns {Promise<void>}
19+
*/
820
export const login = async (request, page, host, token) => {
921
await Promise.resolve(
1022
await request.get(`${host}/login/session_token`, {
@@ -23,7 +35,19 @@ export const login = async (request, page, host, token) => {
2335
)
2436
}
2537

26-
export const grantAccessIfNeeded = async(page, context, toolUrl) => {
38+
39+
/**
40+
* Visit `toolUrl` and complete the grant-access flow if the tool requests it.
41+
* Navigates the page into the LTI tool, waits for loading to finish and
42+
* resolves whether the tool requires an explicit grant. If required, the
43+
* `grantAccess` helper is used to complete the flow.
44+
*
45+
* @param {import('@playwright/test').Page} page - Playwright page instance
46+
* @param {import('@playwright/test').BrowserContext} context - Playwright browser context
47+
* @param {string} toolUrl - URL of the LTI tool to visit
48+
* @returns {Promise<void>}
49+
*/
50+
export const grantAccessIfNeeded = async (page, context, toolUrl) => {
2751
await page.goto(toolUrl)
2852
const ltiToolFrame = getLtiIFrame(page)
2953

@@ -36,49 +60,85 @@ export const grantAccessIfNeeded = async(page, context, toolUrl) => {
3660

3761
const needsGrantAccess = await Promise.race([
3862
ltiToolFrame.getByText('Please Grant Access').waitFor()
39-
.then(() => { return true } ),
63+
.then(() => { return true }),
4064
waitForNoSpinners(ltiToolFrame, 3000)
41-
.then(() => { return false } )
65+
.then(() => { return false })
4266
])
4367

44-
if(needsGrantAccess){
68+
if (needsGrantAccess) {
4569
await grantAccess(context, ltiToolFrame)
4670
}
4771
}
4872

73+
/**
74+
* Complete the grant access flow by clicking the authorise button in the
75+
* popup page. Intended to be used by `grantAccessIfNeeded`.
76+
*
77+
* @param {import('@playwright/test').BrowserContext} context - Playwright browser context
78+
* @param {import('@playwright/test').FrameLocator} frameLocator - Locator for the LTI frame
79+
* @returns {Promise<void>}
80+
*/
4981
const grantAccess = async (context, frameLocator) => {
5082
const button = await frameLocator.getByRole('button')
5183
const [newPage] = await Promise.all([
5284
context.waitForEvent('page'),
5385
button.click()
5486
])
5587

56-
const submit = await newPage.getByRole('button', {name: /Authori[sz]e/})
88+
const submit = await newPage.getByRole('button', { name: /Authori[sz]e/ })
5789
await submit.click()
58-
const close = await newPage.getByText('Close', {exact: true})
90+
const close = await newPage.getByText('Close', { exact: true })
5991
await close.click()
6092
}
6193

94+
95+
/**
96+
* Return the frame locator for the LTI launch iframe.
97+
* @param {import('@playwright/test').Page} page - Playwright page
98+
* @returns {import('@playwright/test').FrameLocator}
99+
*/
62100
export const getLtiIFrame = (page) => {
63101
return page.frameLocator('iframe[data-lti-launch="true"]')
64102
}
65103

66104
let screenshotCount = 1
105+
/**
106+
* Take a screenshot of the provided locator and save it into the test
107+
* output directory. Files are numbered sequentially for the duration of the
108+
* process.
109+
*
110+
* @param {import('@playwright/test').Locator} locator - Locator to screenshot
111+
* @param {{ outputDir: string }} testInfo - Playwright `testInfo` object (only `outputDir` used)
112+
* @returns {Promise<void>}
113+
*/
67114
export const screenshot = async (locator, testInfo) => {
68-
await locator.screenshot({path: `${testInfo.outputDir}/${screenshotCount}.png`, fullPage: true})
115+
await locator.screenshot({ path: `${testInfo.outputDir}/${screenshotCount}.png`, fullPage: true })
69116
screenshotCount++
70117
}
71118

119+
/**
120+
* Dismiss the beta warning banner if present on the current page.
121+
* @param {import('@playwright/test').Page} page - Playwright page
122+
* @returns {Promise<void>}
123+
*/
72124
export const dismissBetaBanner = async (page) => {
73125
if (page.url().includes('beta')) {
74126
const banner = page.getByRole('button', { name: 'Close warning' })
75127
if (await banner.isVisible()) {
76-
await page.getByRole('button', {name: 'Close warning'}).click();
128+
await page.getByRole('button', { name: 'Close warning' }).click()
77129
}
78130
}
79131
}
80132

133+
/**
134+
* Wait for any `.view-spinner` elements inside the supplied frame locator to
135+
* disappear. Optionally provide an initial delay before checking.
136+
*
137+
* @param {import('@playwright/test').FrameLocator} frameLocator - Frame locator to query
138+
* @param {number} [initialDelay=1000] - milliseconds to wait before starting checks
139+
* @returns {Promise<void>}
140+
*/
81141
export const waitForNoSpinners = async (frameLocator, initialDelay = 1000) => {
82-
await new Promise(r => setTimeout(r, initialDelay));
83-
await expect(frameLocator.locator('.view-spinner')).toHaveCount(0, { timeout: 10000 });
142+
await new Promise(r => setTimeout(r, initialDelay))
143+
await expect(frameLocator.locator('.view-spinner')).toHaveCount(0, { timeout: 10000 })
84144
}

0 commit comments

Comments
 (0)