Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

End to End test framework for MSAL 1.0 and 2.0 #1393

Merged
merged 34 commits into from Mar 30, 2020
Merged

Conversation

pkanher617
Copy link
Contributor

@pkanher617 pkanher617 commented Mar 18, 2020

This PR adds an updated end-to-end test framework as well as an updated CLI for samples. It also adds end-to-end tests to the lerna commands as well as to the build pipeline.

@coveralls
Copy link

coveralls commented Mar 18, 2020

Coverage Status

Coverage remained the same at 76.669% when pulling a64fdfa on e2e-test-framework into 2fce441 on dev.

"@azure/msal-browser",
"@azure/msal-angular",
"vanilla-js-test-app",
"vanilla-js-test-app-2.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we confirm msal-node works even with dummy tests? Or is that not a concern?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait! Is this only browser specific end-to-end?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can include all end to end tests with this command, I will change the name to reflect this. For msal-browser and msal-core, the end to end tests are all browser based.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add whatever sample runs your node end to end tests when you have it created.

let username = "";
let accountPwd = "";

function setupScreenshotDir() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are screenshots checked in?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no they are ignored

Copy link
Contributor

@jmckennon jmckennon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall looks great, I personally think there could be value in having something like a TestUtils or TestConstants file that encompasses much of the shared code and strings, because a lot of this stuff is repeated


private async requestLabApi(endpoint: string, accessToken: string): Promise<any> {
try {
const response = await axios(`${labApiUri}${endpoint}`, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

axios is the client we're also using for node, right? wanted to make sure there was consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes thats correct, just wanted something simple to use.

Comment on lines 39 to 48
async function enterCredentials(page: puppeteer.Page, testName: string): Promise<void> {
await page.waitForNavigation({ waitUntil: "networkidle0"});
await takeScreenshot(page, testName, `loginPage`);
await page.type("#i0116", username);
await page.click("#idSIButton9");
await page.waitForNavigation({ waitUntil: "networkidle0"});
await takeScreenshot(page, testName, `pwdInputPage`);
await page.type("#i0118", accountPwd);
await page.click("#idSIButton9");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since I'm less familiar with puppeteer, my understanding is that this flow is basically:

  1. navigate to a page
  2. take a screenshot of the page
  3. crawl the screenshot to verify data is correct

is this all correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No the screenshot is more of utility thing. The crawling occurs on the headless browser page.

Comment on lines 38 to 45
let browser: puppeteer.Browser;
before(async () => {
setupScreenshotDir();
browser = await puppeteer.launch();
});

let context: puppeteer.BrowserContext;
let page: puppeteer.Page;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm assuming that the context and page are not declared at the top because their values depend on puppeteer.launch(), right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we create a new context and page for each test so we have a fresh environment. browser doesn't need to be reloaded every time.

let username = "";
let accountPwd = "";

function setupScreenshotDir() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is implemented in most of these test files, can we just implement it in one place and import each time?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like it could apply to a few functions, like takeScreenshot and potentially setupCredentials

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I am working on creating some test utilities, i will add them as a part of a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Comment on lines 40 to 47
await page.waitForNavigation({ waitUntil: "networkidle0"});
await takeScreenshot(page, testName, `loginPage`);
await page.type("#i0116", username);
await page.click("#idSIButton9");
await page.waitForNavigation({ waitUntil: "networkidle0"});
await takeScreenshot(page, testName, `pwdInputPage`);
await page.type("#i0118", accountPwd);
await page.click("#idSIButton9");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should all of these strings be constants?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will enhance some of this in a future PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@@ -19,8 +18,8 @@ const loginRequest = {

// Add here the endpoints for MS Graph API services you would like to use.
const graphConfig = {
graphMeEndpoint: "Enter_the_Graph_Endpoint_Herev1.0/me",
graphMailEndpoint: "Enter_the_Graph_Endpoint_Herev1.0/me/messages"
graphMeEndpoint: "https://graph.microsoft-ppe.com/v1.0/me",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be using pre-production endpoints?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do for 2.0 until we have a test app that works. I am contacting the labs team to set one up for us.

});
return response.data;
} catch (e) {
console.error(e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-throw instead of returning null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to enhance some of these test utilities in a future PR. for now just getting e2e working.

import axios from "axios";
const labApiUri = "https://msidlab.com/api"

export class TestCredential {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This is more of a LabClient than a TestCredential

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, I can rename

const testEnv = envResponse[0];
if (testEnv.upn) {
username = testEnv.upn;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If lab response doesn't contain upn, maybe log and throw?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to enhance some of these test utilities in a future PR. for now just getting e2e working.

Comment on lines 40 to 47
await page.waitForNavigation({ waitUntil: "networkidle0"});
await takeScreenshot(page, testName, `loginPage`);
await page.type("#i0116", username);
await page.click("#idSIButton9");
await page.waitForNavigation({ waitUntil: "networkidle0"});
await takeScreenshot(page, testName, `pwdInputPage`);
await page.type("#i0118", accountPwd);
await page.click("#idSIButton9");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

let username = "";
let accountPwd = "";

function setupScreenshotDir() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor

@DarylThayil DarylThayil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has my high level approval, if there are specific pieces you want feedback on, please tag them

Copy link
Member

@sameerag sameerag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM as comments will be addressed in future PRs.

@pkanher617 pkanher617 merged commit fa65148 into dev Mar 30, 2020
@pkanher617 pkanher617 deleted the e2e-test-framework branch June 8, 2020 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants