For a long time, I was looking for a way to start end-to-end test solutions in Microsoft Teams. The easiest way to start running these tests is against the web experience (
https://teams.microsoft.com). That way, we can use tools like Cypress. Another reason to do these E2E tests with Cypress is that internally we use Cypress for all our E2E tests.
Unfortunately, for a long time, I have been struggling to make it work, but finally, I found a way to get it running. In this article, I will describe the steps why things fail in Cypress and how to overcome these issues. You also find a link to a sample repository that gets you started quickly.
The problems and solutions
First of all, why is it just not easy to get your tests running in Cypress for Microsoft Teams? There are a couple of complications here.
I like the Cypress UI, it allows you to see the running tests, and go through all the snapshots of each test, but it also has its limitation. To show your running tests in the application, it makes use of an iframe. This iframe approach creates all sorts of issues.
First of all, we have the authentication part. Usually, when navigating to the Microsoft Teams page in your browser, you will get redirected to the sign-in page.
Due to the iframe approach in Cypress, this will give you the following issue:
The Microsoft login page does not like it that you load it from within an iframe.
The solution for this is to make use of a separate login/authentication flow. For this flow, I make use of Playwright.
Info: Playwright is a Node.js library to automate Chromium, Firefox, and WebKit.
The trick here is to do the whole authentication flow within Playwright, grab all the cookies and local storage key-value pairs, and pass these to you Cypress instance.
Check out the teams-auth plugin I wrote for Cypress.
The plugin will first load Microsoft Teams and waits until it navigates you to the login page. Once the page is loaded, it starts entering the username and password. When these steps completed, the plugin grabs all cookies and local storage key-value pairs and passes them to Cypress.
Info: The plugin makes use of playwright-chromium. This dependency makes sure that the footprint is lower as it will only fetch Chromium instead of all the supported browsers.
The iframe problem is not entirely solved. Authentication is the first part of the issue, and once you get past that, you will get stuck on the following page.
Opening the browser console will tell you more about what is happening.
This problem was the hardest to solve, and in the end, it was straightforward to get it resolved.
Microsoft Teams knows you are loading it in an iframe, and wants to prevent you from doing this. I contacted the Cypress team on this matter, but they were not interested in helping out or changing the iframe approach. It is understandable, but getting us past this issue might open a lot of useful use cases, like bot testing and such.
The only answer I got from the Cypress team was to override the method/function, which checks if the application runs in an iframe. Sadly, I had already tried this approach by implementing the overwrite in the
onLoad functions of the
cy.visit method. For a few times I got it working, but I was just lucky.
I found the solution by checking the event catalog from Cypress: Catalog of events. At the end of the page, you find a screenshot that shows all the events in their chronologic order.
The event I was looking for the whole time, was the
window:load one. With this event hook, we are now able to override the default Microsoft Teams iframe check. How this works is as follows:
This code looks hackish, but unfortunately, this is currently the only way for us to get it up and running. As the
teamspace instance has other methods, we have to wait until it is loaded. That is why the
setTimeout functionality is in place. Once it is available, only the
isInIFrame method gets overwritten.
Again, this will not work on the first try. Cypress will return the following error message:
The solution here is to bypass the browser its security warnings. You can do this by setting
false in the
cypress.json config file.
Cookies and local storage
In the previous section, I mentioned Playwright is used for the authentication flow and pass the cookies and local storage. We require these cookies and local storage key-value pairs in Cypress to authenticate and start testing. The problem is that Cypress, by default, clears all cookies and local storage between each test. To overcome this, you can whitelist cookie names. Unfortunately, nothing exists to preserve the local storage, so what you can do is override the clear method. You can find this override in the support index.ts file.
Once you get past all these issues, you will finally be able to start your tests.
Info: This was just a simple test, but it unlocks a lot of potential. This enables you to start testing your chat bots, messaging extensions, tabs, …
A sample project to get you started is available on GitHub: https://github.com/estruyf/cypress-msteams-sample.