Ember CLI Page Object
Ember CLI Page Object is an Ember CLI addon that streamlines the creation and maintenance of page objects for acceptance and integration tests within Ember applications. Following the Page Object design pattern, it abstracts UI interactions and assertions into reusable objects, significantly reducing code duplication and making tests more resilient to UI changes. The current stable version is 2.3.2, released as part of a continuous development cycle with frequent bug fixes and enhancements. Recent efforts have focused on progressively removing jQuery dependencies to modernize the codebase while maintaining backward compatibility. It differentiates itself by providing a dedicated, mature testing pattern specifically tailored for the Ember ecosystem, offering a structured approach to testing complex UIs compared to raw `@ember/test-helpers` usage.
Common errors
-
Error: Assertion Failed: You must provide a selector to `click` or `contains`.
cause Attempting to use an action (like `click`, `contains`) on a page object property without an explicitly defined selector or scope.fixEnsure that the page object property has a `scope` or `selector` defined, or that the action is called on a specific element within the page object hierarchy. E.g., `button: clickable('.my-button')` then `page.button.click()`. -
Module not found: Error: Can't resolve 'ember-cli-page-object/macros'
cause Incorrect import path for page object macros, possibly a typo, or an environment not correctly resolving subpath exports, potentially related to older versions (<2.3.2) or specific bundler configurations.fixVerify the import path for macros (e.g., `import { text } from 'ember-cli-page-object/macros';`). Ensure `ember-cli-page-object` is at least v2.3.2 to benefit from `package.json` exports fixes. -
TypeError: Cannot read properties of undefined (reading 'click') / Element not found for selector '...' in tests.
cause The element targeted by a page object selector does not exist in the DOM when the action is attempted, or an asynchronous action (like `visit()`) hasn't completed before the next action.fixEnsure that `await` is used before any page object action that triggers async behavior (e.g., `await UsersPage.visit();`). Double-check selectors and the rendered HTML for accuracy. Use `await settled()` or `debug()` from `@ember/test-helpers` to inspect the DOM state during tests.
Warnings
- gotcha The library is actively refactoring to remove jQuery usages (e.g., `:visible`, `:hidden`, `$.attr`). While v2.x aims for backward compatibility, custom page object extensions or selectors that rely heavily on jQuery-specific behaviors might encounter subtle changes or breakage in future major versions. Developers are encouraged to migrate away from direct jQuery interactions.
- breaking Ember CLI Page Object has strict compatibility requirements. It requires Ember.js v3.16 or above, Ember CLI v2.13 or above, and Node.js v12, v14, or >= v16. Using older versions of Ember.js, Ember CLI, or Node.js will result in installation failures or runtime errors due to incompatible APIs and module resolution strategies.
- gotcha As of v2.3.2, a fix was implemented for `package.json` exports for index modules. Developers on older versions (<2.3.2) might experience module not found errors, particularly for subpath imports like `/macros`, in environments that strictly adhere to `exports` map resolution or non-standard build setups.
Install
-
npm install ember-cli-page-object -
yarn add ember-cli-page-object -
pnpm add ember-cli-page-object
Imports
- create
const { create } = require('ember-cli-page-object');import { create } from 'ember-cli-page-object'; - visitable
import visitable from 'ember-cli-page-object/macros/visitable';
import { visitable } from 'ember-cli-page-object'; - text
import { text } from 'ember-cli-page-object';import { text } from 'ember-cli-page-object/macros'; - PageObject
import { PageObject } from 'ember-cli-page-object';import type { PageObject } from 'ember-cli-page-object';
Quickstart
import { module, test } from 'qunit';
import { visit, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import { create, visitable, text, collection } from 'ember-cli-page-object';
const UsersPage = create({
visit: visitable('/users'),
title: text('h1'),
users: collection({
itemScope: '.user-item',
item: {
name: text('.user-name'),
email: text('.user-email'),
},
}),
});
module('Acceptance | users', function(hooks) {
setupApplicationTest(hooks);
test('visiting /users', async function(assert) {
// Simulate some data or ensure it's available for the route
// In a real app, this might involve mocking services or Mirage JS
await visit('/users');
assert.equal(currentURL(), '/users');
assert.equal(UsersPage.title, 'Users List');
assert.equal(UsersPage.users.length, 0, 'No users initially'); // Assuming data needs to be loaded
// Example of interacting with a populated list
// (requires data to be present in the tested application)
// await UsersPage.users[0].name.click();
});
});