Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20.11.1
v22.22.3
10 changes: 10 additions & 0 deletions packages/sdk-angular/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
@fusionauth/angular-sdk Changes

Changes in 2.0.0

- Upgraded to Angular 22. Angular 17 through 21 are no longer supported.
- Replaced deprecated `@angular-devkit/build-angular` with `@angular/build`.
- Updated test builder from `@angular-devkit/build-angular:karma` to `@angular/build:unit-test` with `runner: vitest`.
- Bumped `zone.js` from `~0.14.x` to `~0.15.0`.
- Bumped `typescript` from `~5.3.x` to `~6.0.0`.
- Updated `moduleResolution` from `node` to `bundler` in `tsconfig.json`.
- Updated peer dependencies minimum to `>=22.0.0` for `@angular/common` and `@angular/core`.

Changes in 1.3.0

- The `error` passed to [`onAutoRefreshFailure`](https://github.com/FusionAuth/fusionauth-javascript-sdk/blob/main/packages/sdk-angular/docs/interfaces/FusionAuthConfig.md#onautorefreshfailure) should now include the response status code. See [issue #151](https://github.com/FusionAuth/fusionauth-javascript-sdk/issues/151).
Expand Down
9 changes: 5 additions & 4 deletions packages/sdk-angular/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"builder": "@angular/build:ng-packagr",
"options": {
"project": "projects/fusionauth-angular-sdk/ng-package.json"
},
Expand All @@ -25,10 +25,11 @@
"defaultConfiguration": "production"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"builder": "@angular/build:unit-test",
"options": {
"tsConfig": "projects/fusionauth-angular-sdk/tsconfig.spec.json",
"polyfills": ["zone.js", "zone.js/testing"]
"runner": "vitest",
"runnerConfig": "vitest.config.ts",
"tsConfig": "projects/fusionauth-angular-sdk/tsconfig.spec.json"
}
}
}
Expand Down
39 changes: 17 additions & 22 deletions packages/sdk-angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,33 @@
"ng": "ng",
"get-sdk-core": "node getSDKCore.js",
"build": "yarn get-sdk-core && ng build && cp README.md dist/fusionauth-angular-sdk/README.md",
"test": "ng test --watch=false --browsers=ChromeHeadless",
"test": "ng test --watch=false",
"test:watch": "ng test",
"docs": "typedoc --plugin typedoc-plugin-markdown"
},
"private": false,
"dependencies": {
"@angular/animations": "^17.2.0",
"@angular/common": "^17.2.0",
"@angular/compiler": "^17.2.0",
"@angular/core": "^17.2.0",
"@angular/forms": "^17.2.0",
"@angular/platform-browser": "^17.2.0",
"@angular/platform-browser-dynamic": "^17.2.0",
"@angular/router": "^17.2.0",
"@angular/animations": "^22.0.0",
"@angular/common": "^22.0.0",
"@angular/compiler": "^22.0.0",
"@angular/core": "^22.0.0",
"@angular/forms": "^22.0.0",
"@angular/platform-browser": "^22.0.0",
"@angular/platform-browser-dynamic": "^22.0.0",
"@angular/router": "^22.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.2.3",
"@angular/cli": "^17.2.0",
"@angular/compiler-cli": "^17.2.0",
"@angular/build": "^22.0.0",
"@angular/cli": "^22.0.0",
"@angular/compiler-cli": "^22.0.0",
"typedoc": "^0.25.13",
"typedoc-plugin-markdown": "^3.17.1",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^17.2.0",
"typescript": "~5.3.2"
"jsdom": "^25.0.0",
"ng-packagr": "^22.0.0",
"typescript": "~6.0.0",
"vitest": "^4.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "@fusionauth/angular-sdk",
"version": "1.3.0",
"version": "2.0.0",
"peerDependencies": {
"@angular/common": ">=17.2.0",
"@angular/core": ">=17.2.0"
"@angular/common": ">=22.0.0",
"@angular/core": ">=22.0.0"
},
"dependencies": {
"tslib": "^2.3.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
padding: 16px 16px 13px 16px;
border-radius: 8px;
background-color: #083b94;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-size: 18px;
font-weight: 600;
text-align: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
padding: 16px 16px 13px 16px;
border-radius: 8px;
background-color: #083b94;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-size: 18px;
font-weight: 600;
text-align: center;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { vi } from 'vitest';

import { FusionAuthAccountButtonComponent } from './fusion-auth-account-button.component';
import { FusionAuthService } from '../../fusion-auth.service';

describe('FusionauthAccountButtonComponent', () => {
let component: FusionAuthAccountButtonComponent;
let fixture: ComponentFixture<FusionAuthAccountButtonComponent>;
const mockService = jasmine.createSpyObj('FusionAuthService', [
'manageAccount',
]);
const mockService = { manageAccount: vi.fn() };

beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component } from '@angular/core';
import { FusionAuthService } from '../../fusion-auth.service';

@Component({
standalone: false,
selector: 'fa-account',
templateUrl: './fusion-auth-account-button.component.html',
styleUrls: ['./fusion-auth-account-button.component.scss'],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { vi } from 'vitest';

import { FusionAuthLoginButtonComponent } from './fusion-auth-login-button.component';
import { FusionAuthService } from '../../fusion-auth.service';

describe('FusionauthLoginButtonComponent', () => {
let component: FusionAuthLoginButtonComponent;
let fixture: ComponentFixture<FusionAuthLoginButtonComponent>;
const mockService = jasmine.createSpyObj('FusionAuthService', ['startLogin']);
const mockService = { startLogin: vi.fn() };

beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core';
import { FusionAuthService } from '../../fusion-auth.service';

@Component({
standalone: false,
selector: 'fa-login',
templateUrl: './fusion-auth-login-button.component.html',
styleUrls: ['../fa-button.scss', './fusion-auth-login-button.component.scss'],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { vi } from 'vitest';

import { FusionAuthLogoutButtonComponent } from './fusion-auth-logout-button.component';
import { FusionAuthService } from '../../fusion-auth.service';

describe('FusionauthLogoutButtonComponent', () => {
let component: FusionAuthLogoutButtonComponent;
let fixture: ComponentFixture<FusionAuthLogoutButtonComponent>;
const mockService = jasmine.createSpyObj('FusionAuthService', ['logout']);
const mockService = { logout: vi.fn() };

beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component } from '@angular/core';
import { FusionAuthService } from '../../fusion-auth.service';

@Component({
standalone: false,
selector: 'fa-logout',
templateUrl: './fusion-auth-logout-button.component.html',
styleUrls: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { vi } from 'vitest';

import { FusionAuthRegisterButtonComponent } from './fusion-auth-register-button.component';
import { FusionAuthService } from '../../fusion-auth.service';

describe('FusionauthRegisterButtonComponent', () => {
let component: FusionAuthRegisterButtonComponent;
let fixture: ComponentFixture<FusionAuthRegisterButtonComponent>;
const mockService = jasmine.createSpyObj('FusionAuthService', [
'startRegistration',
]);
const mockService = { startRegistration: vi.fn() };

beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core';
import { FusionAuthService } from '../../fusion-auth.service';

@Component({
standalone: false,
selector: 'fa-register',
templateUrl: './fusion-auth-register-button.component.html',
styleUrls: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TestBed } from '@angular/core/testing';
import { fakeAsync, flush, tick } from '@angular/core/testing';
import { vi } from 'vitest';
import { take } from 'rxjs';

import { FusionAuthConfig } from './types';
Expand All @@ -24,72 +24,85 @@ describe('FusionAuthService', () => {
afterEach(() => {
removeAt_expCookie();
localStorage.clear();
vi.restoreAllMocks();
vi.useRealTimers();
});

it('Can be configured to automatically handle getting userInfo', (done: DoneFn) => {
it('Can be configured to automatically handle getting userInfo', async () => {
mockIsLoggedIn();

const user = {
email: 'richard@test.com',
customTrait: 'something special',
};
spyOn(window, 'fetch').and.resolveTo(
vi.spyOn(window, 'fetch').mockResolvedValue(
new Response(JSON.stringify(user), { status: 200 }),
);

const service: FusionAuthService<typeof user> =
configureTestingModule(config);

service.getUserInfoObservable().subscribe({
next: userInfo => {
expect(userInfo.email).toBe('richard@test.com');
expect(userInfo.customTrait).toBe('something special');
done();
},
await new Promise<void>((resolve, reject) => {
service
.getUserInfoObservable()
.pipe(take(1))
.subscribe({
next: userInfo => {
expect(userInfo.email).toBe('richard@test.com');
expect(userInfo.customTrait).toBe('something special');
resolve();
},
error: reject,
});
});
});

it('Handles a failure to get userInfo', (done: DoneFn) => {
it('Handles a failure to get userInfo', async () => {
mockIsLoggedIn();

const responseStatus = 400;
spyOn(window, 'fetch').and.resolveTo(
vi.spyOn(window, 'fetch').mockResolvedValue(
new Response(null, { status: responseStatus }),
);

const service = configureTestingModule(config);

service.getUserInfoObservable().subscribe({
error: error => {
expect(error?.message).toBe(
`Unable to fetch userInfo in fusionauth. Request failed with status code ${responseStatus}`,
);
done();
},
await new Promise<void>((resolve, reject) => {
service
.getUserInfoObservable()
.pipe(take(1))
.subscribe({
error: error => {
expect(error?.message).toBe(
`Unable to fetch userInfo in fusionauth. Request failed with status code ${responseStatus}`,
);
resolve();
},
next: () => reject(new Error('Expected error but got next')),
});
});
});

it("Contains an observable 'isLoggedin$' property that becomes false as the access token expires.", fakeAsync(() => {
it("Contains an observable 'isLoggedIn$' property that becomes false as the access token expires.", async () => {
vi.useFakeTimers();
mockIsLoggedIn(); // sets `app.at_exp` cookie so user is logged in for 1 hour.

const service = configureTestingModule(config);

tick(60 * 59 * 1000);
await vi.advanceTimersByTimeAsync(60 * 59 * 1000);
service.isLoggedIn$.pipe(take(1)).subscribe(isLoggedIn => {
expect(isLoggedIn).toBe(true);
});

tick(60 * 1000); // access token expires
await vi.advanceTimersByTimeAsync(60 * 1000); // access token expires
service.isLoggedIn$.pipe(take(1)).subscribe(isLoggedIn => {
expect(isLoggedIn).toBe(false);
});

flush();
}));
});

it('Can be configured to automatically refresh the access token', () => {
mockIsLoggedIn();
const spy = spyOn(FusionAuthService.prototype, 'initAutoRefresh');
const spy = vi.spyOn(FusionAuthService.prototype, 'initAutoRefresh');

const service = configureTestingModule({
...config,
Expand All @@ -101,7 +114,7 @@ describe('FusionAuthService', () => {
});

it("Does not invoke 'initAutoRefresh' if the user is not logged in", () => {
const initAutoRefreshSpy = spyOn(
const initAutoRefreshSpy = vi.spyOn(
FusionAuthService.prototype,
'initAutoRefresh',
);
Expand All @@ -121,7 +134,7 @@ describe('FusionAuthService', () => {
const stateValue = '/welcome-page';
localStorage.setItem('fa-sdk-redirect-value', `abc123:${stateValue}`);

const onRedirect = jasmine.createSpy('onRedirectSpy');
const onRedirect = vi.fn();
configureTestingModule({ ...config, onRedirect });

expect(onRedirect).toHaveBeenCalledWith('/welcome-page');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Required by Angular's TestBed — zone.js must be imported before zone.js/testing
import 'zone.js';
import 'zone.js/testing';
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
/* To learn more about this file see: https://angular.dev/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": ["jasmine", "node"]
"types": ["vitest/globals", "node"]
},
"include": ["**/*.spec.ts", "**/*.d.ts"]
}
5 changes: 3 additions & 2 deletions packages/sdk-angular/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
/* To learn more about this file see: https://angular.dev/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compileOnSave": false,
Expand All @@ -18,7 +18,8 @@
"sourceMap": true,
"declaration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"ignoreDeprecations": "6.0",
"importHelpers": true,
"target": "ES2022",
"useDefineForClassFields": false,
Expand Down
Loading
Loading