Skip to content

Commit 72abcca

Browse files
authored
fix(angular): export RefresherPullEnd types (#30991)
Issue number: internal --------- ## What is the current behavior? Currently, the 8.8 refresher events are not exported to Angular ## What is the new behavior? With this change, we export the new events and also add Angular tests to validate that they work and will continue working in the future. ## Does this introduce a breaking change? - [ ] Yes - [X] No
1 parent 0e76a69 commit 72abcca

File tree

10 files changed

+133
-6
lines changed

10 files changed

+133
-6
lines changed

core/src/components.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8046,7 +8046,7 @@ declare namespace LocalJSX {
80468046
*/
80478047
"onIonRefresh"?: (event: IonRefresherCustomEvent<RefresherEventDetail>) => void;
80488048
/**
8049-
* Emitted when the user begins to start pulling down. TODO(FW-7044): Remove this in a major release
8049+
* Emitted when the user begins to start pulling down.
80508050
* @deprecated Use `ionPullStart` instead.
80518051
*/
80528052
"onIonStart"?: (event: IonRefresherCustomEvent<void>) => void;

core/src/components/refresher/refresher.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ export class Refresher implements ComponentInterface {
141141
*/
142142
@Event() ionPull!: EventEmitter<void>;
143143

144+
// TODO(FW-7044): Remove this in a major release
144145
/**
145146
* Emitted when the user begins to start pulling down.
146-
* TODO(FW-7044): Remove this in a major release
147147
*
148148
* @deprecated Use `ionPullStart` instead.
149149
*/

packages/angular/src/directives/proxies.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,8 +1831,7 @@ called when the async operation has completed.
18311831
*/
18321832
ionPull: EventEmitter<CustomEvent<void>>;
18331833
/**
1834-
* Emitted when the user begins to start pulling down.
1835-
TODO(FW-7044): Remove this in a major release @deprecated Use `ionPullStart` instead.
1834+
* Emitted when the user begins to start pulling down. @deprecated Use `ionPullStart` instead.
18361835
*/
18371836
ionStart: EventEmitter<CustomEvent<void>>;
18381837
/**

packages/angular/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ export {
114114
RangeKnobMoveEndEventDetail,
115115
RefresherCustomEvent,
116116
RefresherEventDetail,
117+
RefresherPullEndCustomEvent,
118+
RefresherPullEndEventDetail,
117119
ReorderMoveCustomEvent,
118120
ReorderMoveEventDetail,
119121
ReorderEndCustomEvent,

packages/angular/standalone/src/directives/proxies.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,8 +1685,7 @@ called when the async operation has completed.
16851685
*/
16861686
ionPull: EventEmitter<CustomEvent<void>>;
16871687
/**
1688-
* Emitted when the user begins to start pulling down.
1689-
TODO(FW-7044): Remove this in a major release @deprecated Use `ionPullStart` instead.
1688+
* Emitted when the user begins to start pulling down. @deprecated Use `ionPullStart` instead.
16901689
*/
16911690
ionStart: EventEmitter<CustomEvent<void>>;
16921691
/**

packages/angular/standalone/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ export {
112112
RangeKnobMoveEndEventDetail,
113113
RefresherCustomEvent,
114114
RefresherEventDetail,
115+
RefresherPullEndCustomEvent,
116+
RefresherPullEndEventDetail,
115117
ReorderMoveCustomEvent,
116118
ReorderMoveEventDetail,
117119
ReorderEndCustomEvent,
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
/**
4+
* Simulates a pull-to-refresh gesture by dragging from the top of
5+
* the content element downward with intermediate steps so the
6+
* gesture recognizer detects the movement.
7+
*/
8+
const pullDown = async (page: import('@playwright/test').Page, distance: number) => {
9+
const content = page.locator('ion-content');
10+
const box = await content.boundingBox();
11+
if (!box) throw new Error('ion-content not visible');
12+
13+
const startX = box.x + box.width / 2;
14+
const startY = box.y + 30;
15+
16+
await page.mouse.move(startX, startY);
17+
await page.mouse.down();
18+
await page.mouse.move(startX, startY + distance, { steps: 20 });
19+
await page.mouse.up();
20+
};
21+
22+
test.describe('refresher: angular standalone', () => {
23+
test.beforeEach(async ({ page }) => {
24+
await page.goto('/standalone/refresher');
25+
});
26+
27+
test('should emit ionPullStart and ionPullEnd with cancel reason', async ({ page }) => {
28+
// Small drag that doesn't reach the refresh threshold
29+
await pullDown(page, 60);
30+
31+
await page.waitForTimeout(500);
32+
33+
await expect(page.locator('#pull-start-count')).toHaveText('1');
34+
await expect(page.locator('#refresh-count')).toHaveText('0');
35+
await expect(page.locator('#pull-end-count')).toHaveText('1');
36+
await expect(page.locator('#pull-end-reason')).toHaveText('cancel');
37+
});
38+
39+
test('should emit ionPullStart, ionRefresh, and ionPullEnd with complete reason', async ({ page }) => {
40+
// Large drag past the refresh threshold
41+
await pullDown(page, 300);
42+
43+
await page.waitForTimeout(1000);
44+
45+
await expect(page.locator('#pull-start-count')).toHaveText('1');
46+
await expect(page.locator('#refresh-count')).toHaveText('1');
47+
await expect(page.locator('#pull-end-count')).toHaveText('1');
48+
await expect(page.locator('#pull-end-reason')).toHaveText('complete');
49+
});
50+
});

packages/angular/test/base/src/app/standalone/app-standalone/app.routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const routes: Routes = [
3232
{ path: 'providers', loadComponent: () => import('../providers/providers.component').then(c => c.ProvidersComponent) },
3333
{ path: 'overlay-controllers', loadComponent: () => import('../overlay-controllers/overlay-controllers.component').then(c => c.OverlayControllersComponent) },
3434
{ path: 'button', loadComponent: () => import('../button/button.component').then(c => c.ButtonComponent) },
35+
{ path: 'refresher', loadComponent: () => import('../refresher/refresher.component').then(c => c.RefresherComponent) },
3536
{ path: 'reorder-group', loadComponent: () => import('../reorder-group/reorder-group.component').then(c => c.ReorderGroupComponent) },
3637
{ path: 'icon', loadComponent: () => import('../icon/icon.component').then(c => c.IconComponent) },
3738
{ path: 'split-pane', redirectTo: '/standalone/split-pane/inbox', pathMatch: 'full' },

packages/angular/test/base/src/app/standalone/home-page/home-page.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333
Inputs Test
3434
</ion-label>
3535
</ion-item>
36+
<ion-item routerLink="/standalone/refresher">
37+
<ion-label>
38+
Refresher Test
39+
</ion-label>
40+
</ion-item>
3641
<ion-item routerLink="/standalone/reorder-group">
3742
<ion-label>
3843
Reorder Group Test
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Component } from "@angular/core";
2+
import { IonContent, IonHeader, IonItem, IonLabel, IonList, IonRefresher, IonRefresherContent, IonTitle, IonToolbar } from '@ionic/angular/standalone';
3+
import { RefresherCustomEvent, RefresherPullEndCustomEvent } from "@ionic/angular";
4+
5+
@Component({
6+
selector: 'app-refresher',
7+
template: `
8+
<ion-header>
9+
<ion-toolbar>
10+
<ion-title>Refresher Test</ion-title>
11+
</ion-toolbar>
12+
</ion-header>
13+
<ion-content>
14+
<ion-refresher
15+
slot="fixed"
16+
(ionPullStart)="onPullStart()"
17+
(ionRefresh)="onRefresh($event)"
18+
(ionPullEnd)="onPullEnd($event)"
19+
>
20+
<ion-refresher-content></ion-refresher-content>
21+
</ion-refresher>
22+
23+
<ion-list>
24+
<ion-item>
25+
<ion-label>
26+
ionPullStart count: <span id="pull-start-count">{{ pullStartCount }}</span>
27+
</ion-label>
28+
</ion-item>
29+
<ion-item>
30+
<ion-label>
31+
ionRefresh count: <span id="refresh-count">{{ refreshCount }}</span>
32+
</ion-label>
33+
</ion-item>
34+
<ion-item>
35+
<ion-label>
36+
ionPullEnd count: <span id="pull-end-count">{{ pullEndCount }}</span>
37+
</ion-label>
38+
</ion-item>
39+
<ion-item>
40+
<ion-label>
41+
ionPullEnd reason: <span id="pull-end-reason">{{ pullEndReason }}</span>
42+
</ion-label>
43+
</ion-item>
44+
</ion-list>
45+
</ion-content>
46+
`,
47+
standalone: true,
48+
imports: [IonContent, IonHeader, IonItem, IonLabel, IonList, IonRefresher, IonRefresherContent, IonTitle, IonToolbar]
49+
})
50+
export class RefresherComponent {
51+
pullStartCount = 0;
52+
refreshCount = 0;
53+
pullEndCount = 0;
54+
pullEndReason = '';
55+
56+
onPullStart() {
57+
this.pullStartCount++;
58+
}
59+
60+
onRefresh(event: RefresherCustomEvent) {
61+
this.refreshCount++;
62+
event.target.complete();
63+
}
64+
65+
onPullEnd(event: RefresherPullEndCustomEvent) {
66+
this.pullEndCount++;
67+
this.pullEndReason = event.detail.reason;
68+
}
69+
}

0 commit comments

Comments
 (0)