UI test

UI and snapshot testing App UI.

Running this example

To run this example locally:

  1. If you haven't already, create a new app in the Developer Portal(opens in a new tab or window). For more information, refer to our Quickstart guide.

  2. In your app's configuration on the Developer Portal(opens in a new tab or window), ensure the "Development URL" is set to http://localhost:8080.

  3. Clone the starter kit:

    git clone https://github.com/canva-sdks/canva-apps-sdk-starter-kit.git
    cd canva-apps-sdk-starter-kit
    SHELL
  4. Install dependencies:

    npm install
    SHELL
  5. Run the example:

    npm run start ui_test
    SHELL
  6. Click the Preview URL link shown in the terminal to open the example in the Canva editor.

Example app source code

// For usage information, see the README.md file.
import { Button, Rows, Text } from "@canva/app-ui-kit";
import * as styles from "styles/components.css";
export const App = (props: { onClick(): void }) => {
return (
<div className={styles.scrollContainer}>
<Rows spacing="2u">
<Text>This example demonstrates how to test your app's UI.</Text>
<Text>
Check out <code>examples/testing/ui_test/tests/app.tests.tsx</code> to
learn how to start testing.
</Text>
<Button variant="primary" onClick={props.onClick}>
Do something cool
</Button>
</Rows>
</div>
);
};
TYPESCRIPT
// For usage information, see the README.md file.
import { createRoot } from "react-dom/client";
import { App } from "./app";
import "@canva/app-ui-kit/styles.css";
import { AppUiProvider } from "@canva/app-ui-kit";
import { addElementAtPoint } from "@canva/design";
const root = createRoot(document.getElementById("root") as Element);
function render() {
root.render(
<AppUiProvider>
{/* Any Apps SDK method needs to be injected to the component, to avoid the need to mock it in tests */}
<App
onClick={() =>
addElementAtPoint({
type: "text",
children: ["Hello world!"],
})
}
/>
</AppUiProvider>,
);
}
render();
// Hot Module Replacement for development (automatically reloads the app when changes are made)
if (module.hot) {
module.hot.accept("./app", render);
}
TYPESCRIPT
// For usage information, see the README.md file.
// Import Canva SDK testing utilities
import * as asset from "@canva/asset/test";
import * as design from "@canva/design/test";
import * as error from "@canva/error/test";
import * as platform from "@canva/platform/test";
import * as user from "@canva/user/test";
/*
Initialize test environments for each Canva SDK package
This sets up the necessary test infrastructure before mocking the actual SDK methods
*/
asset.initTestEnvironment();
design.initTestEnvironment();
error.initTestEnvironment();
platform.initTestEnvironment();
user.initTestEnvironment();
/*
Mock all Canva SDK packages except @canva/error
This allows tests to run without making real API calls to Canva's services
*/
jest.mock("@canva/asset");
jest.mock("@canva/design");
jest.mock("@canva/platform");
jest.mock("@canva/user");
/*
Important: @canva/error should not be mocked
Use it to simulate API error responses from other mocks by throwing CanvaError instances
This allows testing of error handling scenarios
*/
TYPESCRIPT
// For usage information, see the README.md file.
import { fireEvent, render } from "@testing-library/react";
import { TestAppUiProvider } from "@canva/app-ui-kit";
import { App } from "../app";
describe("app", () => {
let addElementAtPoint: jest.Mock;
beforeEach(() => {
// Create a fresh mock for each test to avoid test interdependency
addElementAtPoint = jest.fn();
});
it("calls addElementAtPoint onClick", async () => {
const result = render(
/*
TestAppUiProvider is used instead of AppUiProvider in tests
It provides the same theming and context without browser-specific features
The theme prop allows testing both light and dark mode appearances
*/
<TestAppUiProvider theme="dark">
<App onClick={addElementAtPoint} />
</TestAppUiProvider>,
);
// Get reference to the button using accessible role selector
const button = result.getByRole("button");
// Verify button text content matches expected value
expect(button.textContent).toEqual("Do something cool");
// Verify the Canva SDK method hasn't been called yet
expect(addElementAtPoint).not.toHaveBeenCalled();
// Simulate user clicking the button
fireEvent.click(button);
// Verify the Canva SDK method was called exactly once
expect(addElementAtPoint).toHaveBeenCalledTimes(1);
});
it("Renders 🎉", () => {
const result = render(
/*
Snapshot testing ensures UI doesn't change unexpectedly
TestAppUiProvider ensures consistent rendering across test environments
*/
<TestAppUiProvider theme="dark">
<App onClick={addElementAtPoint} />
</TestAppUiProvider>,
);
// Compare rendered output against saved snapshot
expect(result.container).toMatchSnapshot();
});
});
TYPESCRIPT
# UI testing
Demonstrates how to set up and write tests for app UI components using standard testing frameworks. Shows basic component testing patterns and provides a foundation for testing user interactions.
For API reference docs and instructions on running this example, see: <https://www.canva.dev/docs/apps/examples/ui-test/>.
Related example: See testing/unit_test for testing app logic and business functions separately from UI.
NOTE: This example differs from what is expected for public apps to pass a Canva review:
- Error handling is simplified for demonstration. Production apps must implement comprehensive error handling with clear user feedback and graceful failure modes
- Internationalization is not implemented. Production apps must support multiple languages using the `@canva/app-i18n-kit` package to pass Canva review requirements
MARKDOWN

API reference

Need help?