Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 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
6 changes: 4 additions & 2 deletions packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@
"clean": "rimraf dist",
"fix:lint": "eslint . --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"test": "vitest",
"test": "vitest --config vitest.node.config.ts",
"test:browser": "vitest --workspace=vitest.workspace.ts",
"test:original": "vitest",
"typecheck": "tsc -p tsconfig.lib.json"
},
"devDependencies": {
Expand All @@ -50,6 +51,7 @@
"esbuild-plugin-inline-worker": "^0.1.1",
"esbuild-plugins-node-modules-polyfill": "^1.7.0",
"eslint": "8.57.0",
"jsdom": "^27.2.0",
"playwright": "^1.55.1",
"prettier": "^2.6.2",
"rimraf": "^6.1.1",
Expand All @@ -74,4 +76,4 @@
"publishConfig": {
"access": "public"
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
}
}

65 changes: 35 additions & 30 deletions packages/browser/src/utils/__tests__/navigate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,66 +16,71 @@
* under the License.
*/

import {vi} from 'vitest';
import {vi, beforeEach, afterEach, describe, it, expect} from 'vitest';
import navigate from '../navigate';

describe('navigate', () => {
const originalLocation = window.location;
let pushStateMock: ReturnType<typeof vi.fn>;
let dispatchEventMock: ReturnType<typeof vi.fn>;
let locationAssignMock: ReturnType<typeof vi.fn>;

beforeEach(() => {
// @ts-ignore
window.history.pushState = vi.fn();
// @ts-ignore
window.dispatchEvent = vi.fn();
// @ts-ignore
window.location.assign = vi.fn();
// @ts-ignore
delete window.location;
// @ts-ignore
window.location = {
...originalLocation,
assign: vi.fn(),
origin: 'https://localhost:5173',
href: 'https://localhost:5173/',
};
// Create mock functions
pushStateMock = vi.fn();
dispatchEventMock = vi.fn(() => true);
locationAssignMock = vi.fn();

// Mock window.history.pushState
vi.stubGlobal('window', {
...window,
history: {
...window.history,
pushState: pushStateMock,
},
dispatchEvent: dispatchEventMock,
location: {
...window.location,
origin: 'https://localhost:5173',
href: 'https://localhost:5173/',
assign: locationAssignMock,
},
});
});

afterEach(() => {
vi.clearAllMocks();
// @ts-ignore
window.location = originalLocation;
vi.unstubAllGlobals();
});

it('should call window.history.pushState with the correct arguments for same-origin', () => {
navigate('/test-url');
expect(window.history.pushState).toHaveBeenCalledWith(null, '', '/test-url');
expect(window.location.assign).not.toHaveBeenCalled();
expect(pushStateMock).toHaveBeenCalledWith(null, '', '/test-url');
expect(locationAssignMock).not.toHaveBeenCalled();
});

it('should dispatch a PopStateEvent with state null for same-origin', () => {
navigate('/test-url');
expect(window.dispatchEvent).toHaveBeenCalledWith(
expect(dispatchEventMock).toHaveBeenCalledWith(
expect.objectContaining({
type: 'popstate',
state: null,
}),
);
expect(window.location.assign).not.toHaveBeenCalled();
expect(locationAssignMock).not.toHaveBeenCalled();
});

it('should use window.location.assign for cross-origin URLs', () => {
const crossOriginUrl = 'https://accounts.asgardeo.io/t/dxlab/accountrecoveryendpoint/register.do';
navigate(crossOriginUrl);
expect(window.location.assign).toHaveBeenCalledWith(crossOriginUrl);
expect(window.history.pushState).not.toHaveBeenCalled();
expect(window.dispatchEvent).not.toHaveBeenCalled();
expect(locationAssignMock).toHaveBeenCalledWith(crossOriginUrl);
expect(pushStateMock).not.toHaveBeenCalled();
expect(dispatchEventMock).not.toHaveBeenCalled();
});

it('should use window.location.assign for malformed URLs', () => {
const malformedUrl = 'http://[::1'; // Invalid URL
navigate(malformedUrl);
expect(window.location.assign).toHaveBeenCalledWith(malformedUrl);
expect(window.history.pushState).not.toHaveBeenCalled();
expect(window.dispatchEvent).not.toHaveBeenCalled();
expect(locationAssignMock).toHaveBeenCalledWith(malformedUrl);
expect(pushStateMock).not.toHaveBeenCalled();
expect(dispatchEventMock).not.toHaveBeenCalled();
});
});
27 changes: 27 additions & 0 deletions packages/browser/vitest.node.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import {defineConfig} from 'vitest/config';

export default defineConfig({
test: {
environment: 'jsdom',
globals: true,
include: ['src/utils/__tests__/navigate.test.ts'],
},
});
2 changes: 1 addition & 1 deletion packages/express/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"clean": "rimraf dist",
"fix:lint": "eslint . --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"test": "vitest",
"test": "vitest run --passWithNoTests",
"typecheck": "tsc -p tsconfig.lib.json"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"clean": "rimraf dist",
"fix:lint": "eslint . --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.cjs,.mjs",
"test": "vitest",
"test": "vitest run --passWithNoTests",
"typecheck": "tsc -p tsconfig.lib.json"
},
"devDependencies": {
Expand Down
15 changes: 0 additions & 15 deletions packages/react-router/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,4 @@ describe('@asgardeo/react-router', () => {
const {ProtectedRoute} = await import('../index');
expect(ProtectedRoute).toBeDefined();
});

it('should export withAuthentication', async () => {
const {withAuthentication} = await import('../index');
expect(withAuthentication).toBeDefined();
});

it('should export useAuthGuard', async () => {
const {useAuthGuard} = await import('../index');
expect(useAuthGuard).toBeDefined();
});

it('should export useReturnUrl', async () => {
const {useReturnUrl} = await import('../index');
expect(useReturnUrl).toBeDefined();
});
});
5 changes: 4 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@
},
"devDependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@types/node": "^22.15.3",
"@types/react": "^19.1.5",
"@vitest/browser": "^3.1.3",
"@wso2/eslint-plugin": "catalog:",
"@wso2/prettier-config": "catalog:",
"esbuild-plugin-preserve-directives": "^0.0.11",
"eslint": "8.57.0",
"jsdom": "^27.2.0",
"playwright": "^1.55.1",
"prettier": "^2.6.2",
"react": "^19.1.0",
Expand All @@ -62,8 +65,8 @@
"react": ">=16.8.0"
},
"dependencies": {
"@asgardeo/i18n": "workspace:^",
"@asgardeo/browser": "workspace:^",
"@asgardeo/i18n": "workspace:^",
"@emotion/css": "^11.13.5",
"@floating-ui/react": "^0.27.12",
"@types/react-dom": "^19.1.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* under the License.
*/

import {render, screen, waitFor} from '@testing-library/react';
import {render, screen, waitFor, cleanup} from '@testing-library/react';
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
import {BaseOrganizationSwitcher, Organization} from './BaseOrganizationSwitcher';
import React from 'react';
Expand All @@ -25,16 +25,65 @@ import React from 'react';
vi.mock('../../../contexts/Theme/useTheme', () => ({
default: () => ({
theme: {
colors: {
text: {primary: '#1a1a1a', secondary: '#666666'},
background: {surface: '#ffffff'},
border: '#e0e0e0',
action: {
hover: 'rgba(0, 0, 0, 0.04)',
selected: 'rgba(0, 0, 0, 0.08)',
focus: 'rgba(0, 0, 0, 0.12)',
},
primary: {
main: '#1a73e8',
contrastText: '#ffffff',
dark: '#174ea6',
},
secondary: {
main: '#424242',
contrastText: '#ffffff',
dark: '#212121',
},
error: {
main: '#d32f2f',
contrastText: '#d52828',
dark: '#b71c1c',
},
},
spacing: {unit: 8},
vars: {
colors: {
text: {primary: '#000', secondary: '#666'},
background: {surface: '#fff'},
border: '#ccc',
action: {hover: '#f0f0f0'},
text: {primary: '#1a1a1a', secondary: '#666666'},
background: {surface: '#ffffff'},
border: '#e0e0e0',
action: {
hover: 'rgba(0, 0, 0, 0.04)',
selected: 'rgba(0, 0, 0, 0.08)',
focus: 'rgba(0, 0, 0, 0.12)',
},
primary: {
main: '#1a73e8',
contrastText: '#ffffff',
dark: '#174ea6',
},
secondary: {
main: '#424242',
contrastText: '#ffffff',
dark: '#212121',
},
},
spacing: {unit: '8px'},
borderRadius: {medium: '4px', large: '8px'},
shadows: {medium: '0 2px 4px rgba(0,0,0,0.1)'},
borderRadius: {small: '4px', medium: '8px', large: '16px'},
shadows: {medium: '0 4px 16px rgba(0, 0, 0, 0.15)'},
typography: {
fontSizes: {
xs: '0.75rem',
sm: '0.875rem',
md: '1rem',
lg: '1.125rem',
xl: '1.25rem',
},
},
},
},
colorScheme: 'light',
Expand Down Expand Up @@ -75,6 +124,7 @@ describe('BaseOrganizationSwitcher RTL Support', () => {

afterEach(() => {
document.documentElement.removeAttribute('dir');
cleanup();
});

it('should render correctly in LTR mode', () => {
Expand All @@ -89,22 +139,24 @@ describe('BaseOrganizationSwitcher RTL Support', () => {
/>,
);

expect(screen.getByText('Organization 1')).toBeInTheDocument();
expect(screen.getByText('Organization 1')).toBeTruthy();
});

it('should render correctly in RTL mode', () => {
document.documentElement.setAttribute('dir', 'rtl');
const handleSwitch = vi.fn();

render(
const {container} = render(
<BaseOrganizationSwitcher
organizations={mockOrganizations}
currentOrganization={mockOrganizations[0]}
onOrganizationSwitch={handleSwitch}
/>,
);

expect(screen.getByText('Organization 1')).toBeInTheDocument();
// Check that the component rendered by finding it in the container
const organizationText = container.querySelector('p');
expect(organizationText?.textContent).toBe('Organization 1');
});

it('should flip chevron icon in RTL mode', async () => {
Expand All @@ -123,9 +175,9 @@ describe('BaseOrganizationSwitcher RTL Support', () => {
const chevronIcon = container.querySelector('svg');
expect(chevronIcon).toBeTruthy();
if (chevronIcon) {
const style = window.getComputedStyle(chevronIcon);
const parentSpan = chevronIcon.parentElement;
// In RTL mode, the transform should be scaleX(-1)
expect(chevronIcon.style.transform).toContain('scaleX(-1)');
expect(parentSpan?.style.transform).toContain('scaleX(-1)');
}
});
});
Expand All @@ -146,8 +198,9 @@ describe('BaseOrganizationSwitcher RTL Support', () => {
const chevronIcon = container.querySelector('svg');
expect(chevronIcon).toBeTruthy();
if (chevronIcon) {
const parentSpan = chevronIcon.parentElement;
// In LTR mode, the transform should be none
expect(chevronIcon.style.transform).toBe('none');
expect(parentSpan?.style.transform).toBe('none');
}
});
});
Expand All @@ -166,7 +219,8 @@ describe('BaseOrganizationSwitcher RTL Support', () => {

// Initially LTR
let chevronIcon = container.querySelector('svg');
expect(chevronIcon?.style.transform).toBe('none');
let parentSpan = chevronIcon?.parentElement;
expect(parentSpan?.style.transform).toBe('none');

// Change to RTL
document.documentElement.setAttribute('dir', 'rtl');
Expand All @@ -182,7 +236,8 @@ describe('BaseOrganizationSwitcher RTL Support', () => {

await waitFor(() => {
chevronIcon = container.querySelector('svg');
expect(chevronIcon?.style.transform).toContain('scaleX(-1)');
parentSpan = chevronIcon?.parentElement;
expect(parentSpan?.style.transform).toContain('scaleX(-1)');
});
});
});
8 changes: 2 additions & 6 deletions packages/react/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ import {defineConfig} from 'vitest/config';

export default defineConfig({
test: {
browser: {
enabled: true,
headless: true,
instances: [{browser: 'chromium'}],
provider: 'playwright',
},
environment: 'jsdom',
globals: true,
},
});
Loading
Loading