Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ Returns **[Promise][71]\<void>** resolves when settled
Checks various settledness metrics (via `getSettledState()`) to determine if things are settled or not.

Settled generally means that there are no pending timers, no pending waiters,
no pending AJAX requests, and no current run loop. However, new settledness
no pending requests, and no current run loop. However, new settledness
metrics may be added and used as they become available.

Returns **[boolean][76]** `true` if settled, `false` otherwise
Expand All @@ -695,13 +695,12 @@ Check various settledness metrics, and return an object with the following prope
* `hasPendingWaiters` - Checks if any registered test waiters are still
pending (e.g. the waiter returns `true`). If there are pending waiters,
this will be `true`, otherwise `false`.
* `hasPendingRequests` - Checks if there are pending AJAX requests (based on
`ajaxSend` / `ajaxComplete` events triggered by `jQuery.ajax`). If there
* `hasPendingRequests` - Checks if there are pending requests. If there
are pending requests, this will be `true`, otherwise `false`.
* `hasPendingTransitions` - Checks if there are pending route transitions. If the
router has not been instantiated / setup for the test yet this will return `null`,
if there are pending transitions, this will be `true`, otherwise `false`.
* `pendingRequestCount` - The count of pending AJAX requests.
* `pendingRequestCount` - The count of pending requests.
* `debugInfo` - Debug information that's combined with info return from backburner's
getDebugInfo method.
* `isRenderPending` - Checks if there are any pending render operations. This will be true as long
Expand Down Expand Up @@ -821,7 +820,6 @@ Responsible for:
* sets the "global testing context" to the provided context (`setContext`)
* create an owner object and set it on the provided context (e.g. `this.owner`)
* setup `this.set`, `this.setProperties`, `this.get`, and `this.getProperties` to the provided context
* setting up AJAX listeners
* setting up `pauseTest` (also available as `this.pauseTest()`) and `resumeTest` helpers

#### Parameters
Expand Down Expand Up @@ -863,7 +861,6 @@ Responsible for:

* un-setting the "global testing context" (`unsetContext`)
* destroy the contexts owner object
* remove AJAX listeners

#### Parameters

Expand Down Expand Up @@ -1030,7 +1027,7 @@ etc. that are then used in a template) has been updated in the DOM.
For example, in a test you might want to update some tracked state and
then run some assertions after rendering has completed. You *could* use
`await settled()` in that location, but in some contexts you don't want to
wait for full settledness (which includes test waiters, pending AJAX/fetch,
wait for full settledness (which includes test waiters, pending fetch,
run loops, etc) but instead only want to know when that updated value has
been rendered in the DOM. **THAT** is what `await rerender()` is *perfect*
for.
Expand Down
4 changes: 2 additions & 2 deletions addon/src/-internal/debug-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
type PendingWaiterState,
} from '@ember/test-waiters';

const PENDING_AJAX_REQUESTS = 'Pending AJAX requests';
const PENDING_REQUESTS = 'Pending requests';
const PENDING_TEST_WAITERS = 'Pending test waiters';
const SCHEDULED_ASYNC = 'Scheduled async';
const SCHEDULED_AUTORUN = 'Scheduled autorun';
Expand Down Expand Up @@ -158,7 +158,7 @@ export class TestDebugInfo implements DebugInfo {
const summary = this.summary;

if (summary.hasPendingRequests) {
_console.log(PENDING_AJAX_REQUESTS);
_console.log(PENDING_REQUESTS);
}

if (summary.hasPendingLegacyWaiters) {
Expand Down
2 changes: 1 addition & 1 deletion addon/src/rerender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import renderSettled from './-internal/render-settled.ts';
For example, in a test you might want to update some tracked state and
then run some assertions after rendering has completed. You _could_ use
`await settled()` in that location, but in some contexts you don't want to
wait for full settledness (which includes test waiters, pending AJAX/fetch,
wait for full settledness (which includes test waiters, pending fetch,
run loops, etc) but instead only want to know when that updated value has
been rendered in the DOM. **THAT** is what `await rerender()` is _perfect_
for.
Expand Down
93 changes: 4 additions & 89 deletions addon/src/settled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,104 +5,20 @@ import { _backburner } from '@ember/runloop';
import { Test } from 'ember-testing';
import { pendingRequests as _internalGetPendingRequestsCount } from 'ember-testing/lib/test/pending_requests';

import { nextTick } from './-utils.ts';
import waitUntil from './wait-until.ts';
import { hasPendingTransitions } from './setup-application-context.ts';
import { hasPendingWaiters } from '@ember/test-waiters';
import type DebugInfo from './-internal/debug-info.ts';
import { TestDebugInfo } from './-internal/debug-info.ts';

let requests: XMLHttpRequest[];
const checkWaiters = Test.checkWaiters;

/**
@private
@returns {number} the count of pending requests
*/
function pendingRequests() {
const localRequestsPending = requests !== undefined ? requests.length : 0;
const internalRequestsPending = _internalGetPendingRequestsCount();

return localRequestsPending + internalRequestsPending;
}

/**
@private
@param {Event} event (unused)
@param {XMLHTTPRequest} xhr the XHR that has initiated a request
*/
function incrementAjaxPendingRequests(event: any, xhr: XMLHttpRequest): void {
requests.push(xhr);
}

/**
@private
@param {Event} event (unused)
@param {XMLHTTPRequest} xhr the XHR that has initiated a request
*/
function decrementAjaxPendingRequests(event: any, xhr: XMLHttpRequest): void {
// In most Ember versions to date (current version is 2.16) RSVP promises are
// configured to flush in the actions queue of the Ember run loop, however it
// is possible that in the future this changes to use "true" micro-task
// queues.
//
// The entire point here, is that _whenever_ promises are resolved will be
// before the next run of the JS event loop. Then in the next event loop this
// counter will decrement. In the specific case of AJAX, this means that any
// promises chained off of `$.ajax` will properly have their `.then` called
// _before_ this is decremented (and testing continues)
nextTick(() => {
for (let i = 0; i < requests.length; i++) {
if (xhr === requests[i]) {
requests.splice(i, 1);
}
}
});
}

/**
Clears listeners that were previously setup for `ajaxSend` and `ajaxComplete`.

@private
*/
export function _teardownAJAXHooks() {
// jQuery will not invoke `ajaxComplete` if
// 1. `transport.send` throws synchronously and
// 2. it has an `error` option which also throws synchronously

// We can no longer handle any remaining requests
requests = [];

if (typeof (globalThis as any).jQuery === 'undefined') {
return;
}

(globalThis as any)
.jQuery(document)
.off('ajaxSend', incrementAjaxPendingRequests);
(globalThis as any)
.jQuery(document)
.off('ajaxComplete', decrementAjaxPendingRequests);
}

/**
Sets up listeners for `ajaxSend` and `ajaxComplete`.

@private
*/
export function _setupAJAXHooks() {
requests = [];

if (typeof (globalThis as any).jQuery === 'undefined') {
return;
}

(globalThis as any)
.jQuery(document)
.on('ajaxSend', incrementAjaxPendingRequests);
(globalThis as any)
.jQuery(document)
.on('ajaxComplete', decrementAjaxPendingRequests);
return _internalGetPendingRequestsCount();
}

export interface SettledState {
Expand All @@ -127,13 +43,12 @@ export interface SettledState {
- `hasPendingWaiters` - Checks if any registered test waiters are still
pending (e.g. the waiter returns `true`). If there are pending waiters,
this will be `true`, otherwise `false`.
- `hasPendingRequests` - Checks if there are pending AJAX requests (based on
`ajaxSend` / `ajaxComplete` events triggered by `jQuery.ajax`). If there
- `hasPendingRequests` - Checks if there are pending requests. If there
are pending requests, this will be `true`, otherwise `false`.
- `hasPendingTransitions` - Checks if there are pending route transitions. If the
router has not been instantiated / setup for the test yet this will return `null`,
if there are pending transitions, this will be `true`, otherwise `false`.
- `pendingRequestCount` - The count of pending AJAX requests.
- `pendingRequestCount` - The count of pending requests.
- `debugInfo` - Debug information that's combined with info return from backburner's
getDebugInfo method.
- `isRenderPending` - Checks if there are any pending render operations. This will be true as long
Expand Down Expand Up @@ -176,7 +91,7 @@ export function getSettledState(): SettledState {
Checks various settledness metrics (via `getSettledState()`) to determine if things are settled or not.

Settled generally means that there are no pending timers, no pending waiters,
no pending AJAX requests, and no current run loop. However, new settledness
no pending requests, and no current run loop. However, new settledness
metrics may be added and used as they become available.

@public
Expand Down
4 changes: 0 additions & 4 deletions addon/src/setup-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { Resolver } from '@ember/owner';
import { setOwner } from '@ember/application';

import buildOwner, { type Owner } from './build-owner.ts';
import { _setupAJAXHooks } from './settled.ts';
import { _prepareOnerror } from './setup-onerror.ts';
import { setTesting } from '@ember/debug';
import {
Expand Down Expand Up @@ -363,7 +362,6 @@ export function getWarningsDuringCallback(
- sets the "global testing context" to the provided context (`setContext`)
- create an owner object and set it on the provided context (e.g. `this.owner`)
- setup `this.set`, `this.setProperties`, `this.get`, and `this.getProperties` to the provided context
- setting up AJAX listeners
- setting up `pauseTest` (also available as `this.pauseTest()`) and `resumeTest` helpers

@public
Expand Down Expand Up @@ -486,8 +484,6 @@ export default function setupContext<T extends object>(
});
};

_setupAJAXHooks();

return context;
});
}
4 changes: 1 addition & 3 deletions addon/src/teardown-context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { TestContext } from './setup-context';
import { setTesting } from '@ember/debug';
import { unsetContext } from './setup-context.ts';
import settled, { _teardownAJAXHooks } from './settled.ts';
import settled from './settled.ts';
import { _cleanupOnerror } from './setup-onerror.ts';
import { destroy } from '@ember/destroyable';

Expand All @@ -16,7 +16,6 @@ export interface TeardownContextOptions {

- un-setting the "global testing context" (`unsetContext`)
- destroy the contexts owner object
- remove AJAX listeners

@public
@param {Object} context the context to setup
Expand All @@ -31,7 +30,6 @@ export default function teardownContext(
return Promise.resolve()
.then(() => {
_cleanupOnerror(context);
_teardownAJAXHooks();

setTesting(false);
unsetContext();
Expand Down
2 changes: 0 additions & 2 deletions test-app/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ module.exports = {
'ember/no-empty-glimmer-component-classes': 'off',
'ember/no-get': 'off',
'ember/require-super-in-lifecycle-hooks': 'off',
'ember/no-global-jquery': 'off',
'ember/no-jquery': 'off',
'ember/no-legacy-test-waiters': 'off',
'ember/no-pause-test': 'off',
'ember/no-settled-after-test-helper': 'off',
Expand Down
4 changes: 1 addition & 3 deletions test-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"lint:hbs:fix": "ember-template-lint . --fix",
"lint:js": "eslint . --cache",
"lint:js:fix": "eslint . --fix",
"start": "pnpm _syncPnpm && concurrently 'ember serve' 'pnpm _syncPnpm --watch' --names 'tests serve,tests sync deps'",
"start": "pnpm _syncPnpm && concurrently 'ember serve --port=0' 'pnpm _syncPnpm --watch' --names 'tests serve,tests sync deps'",
Copy link
Member Author

Choose a reason for hiding this comment

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

Oh woops, don't think this change should've been committed. Will revert.

"test": "pnpm _syncPnpm; ember test",
"test:ember": "ember test",
"_syncPnpm": "DEBUG=sync-pnpm pnpm sync-dependencies-meta-injected"
Expand All @@ -31,7 +31,6 @@
"devDependencies": {
"@babel/eslint-parser": "^7.21.3",
"@babel/plugin-proposal-decorators": "^7.21.0",
"@ember/jquery": "^2.0.0",
"@ember/optional-features": "^2.0.0",
"@ember/string": "^3.0.1",
"@ember/test-helpers": "workspace:*",
Expand Down Expand Up @@ -67,7 +66,6 @@
"latest-version": "^5.0.0",
"loader.js": "^4.7.0",
"pnpm-sync-dependencies-meta-injected": "^0.0.14",
"pretender": "^3.4.7",
"prettier": "^2.8.7",
"qunit": "^2.21.1",
"qunit-console-grouper": "^0.3.0",
Expand Down
Loading
Loading