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 studio-frontend/docker/10-runtime-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# variables at container start. nginx:alpine runs every /docker-entrypoint.d
# script before starting nginx — no custom ENTRYPOINT needed.
#
# The generated file sets window.__STUDIO_ENV__ (see src/env.ts): runtime
# The generated file sets window.__STUDIO_ENV__ (see src-app/app/config/env.ts): runtime
# values beat the build-time VITE_* fallbacks, so one image serves any
# environment.
set -eu
Expand Down
3 changes: 3 additions & 0 deletions studio-frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
</head>
<body>
<div id="root"></div>
<!-- Runtime env must load before the bundle: the container entrypoint
rewrites /env.js, and src-app/app/config/env.ts reads it at import. -->
<script src="/env.js"></script>
<script type="module" src="/src-app/app/main.tsx"></script>
</body>
</html>
4 changes: 4 additions & 0 deletions studio-frontend/public/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Dev placeholder. In containers, docker/10-runtime-env.sh overwrites this
// file at startup with values from STUDIO_* environment variables
// (see src-app/app/config/env.ts for the reading side).
window.__STUDIO_ENV__ = {};

This file was deleted.

This file was deleted.

35 changes: 0 additions & 35 deletions studio-frontend/src-app/__test-utils__/mockUserFixture.ts

This file was deleted.

11 changes: 8 additions & 3 deletions studio-frontend/src-app/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,18 @@
import { Layout } from '@/app/layout';
import { StudioOverlay } from '@gears-frontx/studio';
import { MfeScreenContainer } from '@/app/mfe/MfeScreenContainer';
import { AuthGate } from '@/app/auth/AuthGate';

function App() {
return (
<>
<Layout>
<MfeScreenContainer />
</Layout>
{/* The authenticated app mounts only behind the gate; the dev overlay
stays outside so theme/mock toggles work on the login screen too. */}
<AuthGate>
<Layout>
<MfeScreenContainer />
</Layout>
</AuthGate>
<StudioOverlay />
</>
);
Expand Down
10 changes: 0 additions & 10 deletions studio-frontend/src-app/app/actions/bootstrapActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*/

import { eventBus } from '@gears-frontx/react';
import type { ApiUser } from '@/app/api';

/**
* Fetch current user
Expand All @@ -18,13 +17,4 @@ import type { ApiUser } from '@/app/api';
export function fetchCurrentUser(): void {
eventBus.emit('app/user/fetch');
}

/**
* Notify that user data has been loaded
* Called by screens after successfully fetching user data.
* Emits 'app/user/loaded' event so header state updates.
*/
export function notifyUserLoaded(user: ApiUser): void {
eventBus.emit('app/user/loaded', { user });
}
// @cpt-end:cpt-frontx-flow-framework-composition-app-bootstrap:p1:inst-1
28 changes: 20 additions & 8 deletions studio-frontend/src-app/app/api/AccountsApiService.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { describe, expect, it } from 'vitest';
import { AccountsApiService } from './AccountsApiService';
import { resetAccountsMockState } from './__test-utils__/mocks';
import { UserRole } from './types';
import { describeAccountsApiServiceContract } from '@frontx-test-utils/describeAccountsApiServiceContract';
import { attachRegisteredRestMocks } from '@frontx-test-utils/attachRegisteredRestMocks';

describeAccountsApiServiceContract({
suiteName: 'AccountsApiService',
createService: () => new AccountsApiService(),
resetAccountsMockState,
adminRole: UserRole.Admin,
describe('AccountsApiService', () => {
it('exposes the /me identity endpoint against the account-management gear', async () => {
const service = new AccountsApiService();
attachRegisteredRestMocks(service);

const key = service.me.key;
expect(key).toHaveLength(3);
expect(key[1]).toBe('GET');
expect(String(key[2])).toBe('/me');

// Resolving through the registered mock proves the full URL
// (baseURL /cf/account-management/v1 + /me) matches the mock map key.
await expect(service.me.fetch()).resolves.toEqual({
subject_id: expect.any(String),
subject_type: 'user',
subject_tenant_id: expect.any(String),
});
});
});
16 changes: 12 additions & 4 deletions studio-frontend/src-app/app/api/AccountsApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ import {
RestProtocol,
RestMockPlugin,
} from '@gears-frontx/react';
import type { GetCurrentUserResponse } from './types';
import type { Me } from './types';
import { accountsMockMap } from './mocks';

/**
* The real account-management gear behind the /cf gateway prefix
* (vite dev proxy / nginx location — same-origin in every environment).
* Exported so raw probes (LoginScreen's pre-session token check) stay on
* the same base as the service.
*/
export const ACCOUNTS_API_BASE_URL = '/cf/account-management/v1';

/**
* Accounts API Service
* Manages accounts domain endpoints:
Expand All @@ -27,7 +35,7 @@ export class AccountsApiService extends BaseApiService {
});
const restEndpoints = new RestEndpointProtocol(restProtocol);

super({ baseURL: '/api/accounts' }, restProtocol, restEndpoints);
super({ baseURL: ACCOUNTS_API_BASE_URL }, restProtocol, restEndpoints);

// Register mock plugin (framework controls when it's active based on mock mode toggle)
this.registerPlugin(
Expand All @@ -39,6 +47,6 @@ export class AccountsApiService extends BaseApiService {
);
}

readonly getCurrentUser = this.protocol(RestEndpointProtocol)
.query<GetCurrentUserResponse>('/user/current');
/** Identity check against the backend: who does this token authenticate as. */
readonly me = this.protocol(RestEndpointProtocol).query<Me>('/me');
}
18 changes: 0 additions & 18 deletions studio-frontend/src-app/app/api/__test-utils__/mocks.ts

This file was deleted.

4 changes: 2 additions & 2 deletions studio-frontend/src-app/app/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
* Application-specific API exports
*/

export { AccountsApiService } from './AccountsApiService';
export { UserRole, type ApiUser, type UserExtra, type GetCurrentUserResponse } from './types';
export { AccountsApiService, ACCOUNTS_API_BASE_URL } from './AccountsApiService';
export { type Me } from './types';
export { accountsMockMap } from './mocks';
29 changes: 0 additions & 29 deletions studio-frontend/src-app/app/api/mock-user-store.ts

This file was deleted.

35 changes: 10 additions & 25 deletions studio-frontend/src-app/app/api/mocks.test.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
import { beforeEach, describe, expect, it } from 'vitest';
import { describe, expect, it } from 'vitest';
import { accountsMockMap } from './mocks';
import { getMockUser, resetAccountsMockState } from './__test-utils__/mocks';

describe('accountsMockMap', () => {
beforeEach(() => {
resetAccountsMockState();
});

it('returns the current mock user instance', () => {
const getCurrentUser = accountsMockMap['GET /api/accounts/user/current'];

expect(getCurrentUser()).toEqual({ user: getMockUser() });
});

it('restores the default mock user after state reset', () => {
const initialUser = getMockUser();

initialUser.firstName = 'Changed';

resetAccountsMockState();
it('serves the identity check on the real gateway URL', () => {
const handler = accountsMockMap['GET /cf/account-management/v1/me'];
expect(handler).toBeTypeOf('function');

expect(getMockUser()).toEqual(
expect.objectContaining({
id: 'mock-user-001',
firstName: 'Demo',
}),
);
expect(getMockUser()).not.toBe(initialUser);
const me = (handler as () => unknown)();
expect(me).toEqual({
subject_id: expect.any(String),
subject_type: 'user',
subject_tenant_id: expect.any(String),
});
});
});
11 changes: 6 additions & 5 deletions studio-frontend/src-app/app/api/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
*/

import type { MockMap } from '@gears-frontx/react';
import type { GetCurrentUserResponse } from './types';
import { readCurrentAccountsMockUser } from './mock-user-store';
import type { Me } from './types';

/**
* Accounts mock map
* Keys are full URL patterns (including /api/accounts baseURL)
* Keys are full URL patterns (including the /cf/account-management/v1 baseURL)
*/
export const accountsMockMap: MockMap = {
'GET /api/accounts/user/current': (): GetCurrentUserResponse => ({
user: readCurrentAccountsMockUser(),
'GET /cf/account-management/v1/me': (): Me => ({
subject_id: '00000000-0000-0000-0000-000000000001',
subject_type: 'user',
subject_tenant_id: '00000000-0000-0000-0000-0000000000aa',
}),
};
Loading
Loading