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
26 changes: 26 additions & 0 deletions .github/workflows/actions/test-angular-package/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: 'Test Ionic Angular Package'
description: 'Test Ionic Angular Package'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-angular
path: ./packages/angular
filename: AngularBuild.zip
- name: 🕸️ Install Angular Dependencies
run: npm ci
Comment thread
OS-jacobbell marked this conversation as resolved.
shell: bash
working-directory: ./packages/angular
- name: 📐 Run Angular Package Tests
run: npm run test
shell: bash
working-directory: ./packages/angular
7 changes: 7 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/workflows/actions/build-angular

test-angular-package:
needs: [build-angular]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/workflows/actions/test-angular-package

build-angular-server:
needs: [build-core]
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ core/docker-display-volume.txt
# angular
packages/angular/css/
packages/angular/test/build/
packages/angular/test/code-split-build/
.angular/

# vue
Expand Down
20 changes: 20 additions & 0 deletions packages/angular/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,23 @@ Ionic developers can access this by importing from `@ionic/angular/lazy`.

> [!CAUTION]
> The lazy loaded build, including `IonicModule`, is deprecated and will be removed in a future major version. New code should use the standalone components and `provideIonicAngular()` imported from `@ionic/angular`.

## Package Validation

`npm run validate` executes several subtasks: installs node modules, lints, builds the package, and runs package tests. `npm run test` can also run the package tests directly. For E2E tests, see [Angular Testing documentation](/docs/angular/testing.md).

### Testing Package Exports

To check that all exports from `package.json` point to files that exist, and that all Ionic components have exports, run `node ./scripts/verify-exports.js` or `npm run test.package`.

### Testing Code Splitting

If an app imports standalone components from `@ionic/angular`, esbuild bundles them together, so a landing page could include components it never uses. If components are instead imported from `@ionic/angular/<component-name>`, esbuild is able to bundle pages with only the components they need. The app in `packages/angular/test/code-split` is used to verify that this code splitting is working.

To run the test, run `node ./scripts/test-code-split.js` or run `npm run test.code-split`. This builds the code-split app and checks if `IonToggle` is excluded from the landing page's bundle.

### Testing Schematics

The schematics files are used when Ionic-Angular is added to a project with `ng add`. The schematics test verifies schematics are included in the package by creating a new starter app and adding the locally built Ionic-Angular package to it.

To run the test, run `node ./scripts/verify-schematics.js` or run `npm run test.schematics`.
17 changes: 13 additions & 4 deletions packages/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"homepage": "https://ionicframework.com/",
"scripts": {
"build": "npm run clean && npm run build.ng && npm run build.css && npm run build.schematics && npm run validate.package",
"build": "npm run clean && npm run build.ng && npm run build.css && npm run build.schematics",
"build.css": "node scripts/build-css.js",
"build.schematics": "node scripts/build-schematics.js",
"build.ng": "ngc",
Expand All @@ -37,9 +37,11 @@
"prerelease": "npm run validate && np prerelease --yolo --any-branch --tag next",
"sync": "./scripts/sync.sh",
"local.sync.and.pack": "./scripts/sync-and-pack.sh",
"test": "echo 'angular no tests yet'",
"validate": "npm i && npm run lint && npm run test && npm run build",
"validate.package": "node scripts/verify-exports.js"
"test": "npm run test.schematics && npm run test.code-split && npm run test.package",
"test.code-split": "node ./scripts/test-code-split.js",
"test.schematics": "node ./scripts/verify-schematics.js",
"test.package": "node scripts/verify-exports.js",
"validate": "npm i && npm run lint && npm run build && npm run test"
},
"exports": {
"./package.json": "./package.json",
Expand Down Expand Up @@ -141,6 +143,13 @@
"./ion-title": "./dist/standalone/directives/ion-title.js",
"./ion-toast": "./dist/standalone/directives/ion-toast.js",
"./ion-toolbar": "./dist/standalone/directives/ion-toolbar.js",
"./dom-controller": "./dist/common/providers/dom-controller.js",
"./nav-controller": "./dist/common/providers/nav-controller.js",
"./config": "./dist/common/providers/config.js",
"./platform": "./dist/common/providers/platform.js",
"./nav-params": "./dist/common/directives/navigation/nav-params.js",
"./ion-modal-token": "./dist/standalone/providers/modal-token.js",
"./ionic-route-strategy": "./dist/common/utils/routing.js",
"./action-sheet-controller": "./dist/standalone/providers/action-sheet-controller.js",
"./alert-controller": "./dist/standalone/providers/alert-controller.js",
"./animation-controller": "./dist/standalone/providers/animation-controller.js",
Expand Down
76 changes: 76 additions & 0 deletions packages/angular/scripts/test-code-split.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* Validates that per-component imports let a bundler code-split Ionic components.
* Inspects `www/stats.json`, the esbuild metafile, to see which output chunk a
* component landed in. `ion-toggle` is used by only the home page, so it
* should not be bundled with the landing page.
*
* Build core and the angular package before running this test.
*/

const fs = require('fs-extra');
const path = require('path');
const { execSync } = require('node:child_process');

const PROJECT_DIR = path.join(__dirname, '../test/code-split');
const STATS_FILE = path.join(PROJECT_DIR, 'www/stats.json');


function collectChunks(stats, startChunkName, chunkSet)
{
chunkSet.add(startChunkName);
const chunk = stats.outputs[startChunkName]
for (const imported of chunk.imports) {
if (imported.kind === "import-statement" && !chunkSet.has(imported.path)) {
collectChunks(stats, imported.path, chunkSet);
}
}
}

function findChunksForPage(stats, page) {
const chunkSet = new Set();

for (const [chunkName, chunkData] of Object.entries(stats.outputs || {})) {
if (chunkName.endsWith('.js')) {
const importFound = Object.keys(chunkData.inputs).some(input => input.endsWith(page));
if (importFound) {
collectChunks(stats, chunkName, chunkSet);
}
}
}

return chunkSet;
}

function hasComponentAsInput(stats, chunks, component) {
for (const chunk of chunks) {
for (const inputName of Object.keys(stats.outputs[chunk].inputs)) {
if (inputName.endsWith(component)) {
return true;
}
}
}
return false;
}

function main() {
try {
execSync('npm i', { cwd: PROJECT_DIR });
execSync('./sync.sh', { cwd: PROJECT_DIR });
execSync(`npm run build`, { cwd: PROJECT_DIR, stdio: 'inherit' });

const stats = fs.readJsonSync(STATS_FILE);
const chunks = findChunksForPage(stats, 'landing.page.ts');

const splitComponent = 'ion-toggle.js';
if (hasComponentAsInput(stats, chunks, splitComponent)) {
throw new Error(`${splitComponent} was not split from landing page.`);
}

console.log('✅ verified code-split');
} catch (error) {
process.exitCode = 1;
console.error(error);
}
}

main();
5 changes: 4 additions & 1 deletion packages/angular/scripts/verify-exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const KNOWN_EXCLUDED_COMPONENTS = [
'ion-select-popover',
'ion-slides',
];
const KNOWN_NON_CORE_ION_COMPONENTS = [
'ion-modal-token',
];

function getComponentsFromCore() {
const componentsList = fs.readdirSync(CORE_COMPONENTS_DIR, { withFileTypes: true })
Expand Down Expand Up @@ -60,7 +63,7 @@ function verify() {

// Check for exports that don't have a corresponding component in core
for (const exportName of Object.keys(ionExports)) {
if (!coreComponents.has(exportName)) {
if (!coreComponents.has(exportName) && !KNOWN_NON_CORE_ION_COMPONENTS.includes(exportName)) {
console.log(`${exportName} is exported without a matching component in core.`);
hasErrors = true;
}
Expand Down
34 changes: 34 additions & 0 deletions packages/angular/scripts/verify-schematics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const fs = require('fs-extra');
const path = require('path');
const { execSync } = require('node:child_process');

const testName = 'schematics-test';
const packageRootDir = path.join(__dirname, '..');
const testDir = path.join(packageRootDir, testName);

try {
// Delete old packages
execSync(`rm -f *.tgz`, {cwd: packageRootDir});

// Pack ionic-core
execSync(`npm pack ../../core`, {cwd: packageRootDir});

// Pack ionic-angular
execSync(`npm pack`, {cwd: packageRootDir});

// Create new Angular project
execSync(`npx ng new ${testName} --style css --ssr false --ai-config none`, {cwd: packageRootDir});

// Install ionic-angular and core packages
execSync(`npx ng add --skip-confirmation ../ionic-angular-*`, {cwd: testDir});
Comment thread
OS-jacobbell marked this conversation as resolved.
execSync(`npm install ../*.tgz --no-save`, {cwd: testDir});

// Run build
execSync(`npm run build`, {cwd: testDir});
} catch(error) {
console.log(error);
process.exitCode = 1;
}

fs.removeSync(testDir);
execSync(`rm -f *.tgz`, {cwd: packageRootDir});
19 changes: 8 additions & 11 deletions packages/angular/src/standalone/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,16 @@ export { MenuController } from './providers/menu-controller';
export { ModalController } from './providers/modal-controller';
export { PopoverController } from './providers/popover-controller';
export { ToastController } from './providers/toast-controller';
export {
DomController,
NavController,
Config,
Platform,
NavParams,
IonModalToken,
IonicRouteStrategy,
export { IonModalToken } from './providers/modal-token';
export { DomController, NavController, Config, Platform, NavParams, IonicRouteStrategy } from '@ionic/angular/common';
export type {
ViewWillEnter,
ViewDidEnter,
ViewWillLeave,
ViewDidLeave,
ModalOptions,
PopoverOptions,
} from '@ionic/angular/common';
export type { ModalOptions, PopoverOptions } from '@ionic/angular/common';
export { IonNav } from './navigation/nav';
export {
IonCheckbox,
Expand All @@ -51,11 +47,13 @@ export {
createGesture,
iosTransitionAnimation,
mdTransitionAnimation,
IonicSafeString,
IonicSlides,
getPlatforms,
isPlatform,
getTimeGivenProgression,
// TYPES
} from '@ionic/core/components';
export type {
Comment thread
OS-jacobbell marked this conversation as resolved.
Animation,
AnimationBuilder,
AnimationCallbackOptions,
Expand Down Expand Up @@ -93,7 +91,6 @@ export {
ItemReorderEventDetail,
ItemReorderCustomEvent,
ItemSlidingCustomEvent,
IonicSafeString,
LoadingOptions,
MenuCustomEvent,
ModalDragEventDetail,
Expand Down
1 change: 1 addition & 0 deletions packages/angular/src/standalone/providers/modal-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { IonModalToken } from '@ionic/angular/common';
4 changes: 4 additions & 0 deletions packages/angular/test/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Angular E2E Test Apps

Refer to the [Angular Testing documentation](/docs/angular/testing.md) in order to build and run the test app.

# Code Split Test App

Refer to the "Testing Code Splitting" section in the [Angular Package README](/packages/angular/README.md).
15 changes: 15 additions & 0 deletions packages/angular/test/code-split/.browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries

# For the full list of supported browsers by the Angular framework, please see:
# https://angular.dev/reference/versions#browser-support

# You can see what browsers were selected by your queries by running:
# npx browserslist

Chrome >=107
Firefox >=106
Edge >=107
Safari >=16.1
iOS >=16.1
16 changes: 16 additions & 0 deletions packages/angular/test/code-split/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.ts]
quote_type = single

[*.md]
max_line_length = off
trim_trailing_whitespace = false
Loading
Loading