backend-test-utils: add version field to mock credentials

The mock credentials created by mockCredentials.none(), .user(), and
.service() were missing the internal version: 'v1' field. This caused
toInternalBackstageCredentials() to throw when used with mock
credentials in tests.

Signed-off-by: Fredrik Adelöw <freben@gmail.com>

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2026-05-14 17:30:30 +02:00
parent eab8f7a510
commit ada7df7929
5 changed files with 70 additions and 3 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': patch
---
Fixed `mockCredentials` to include the internal `version: 'v1'` field on all credential objects (`none()`, `user()`, `limitedUser()`, `service()`), and fixed `user()` to encode the user entity ref into the token (matching `user.token(ref)` behavior). This makes mock credentials compatible with `toInternalBackstageCredentials()`, which validates the version field, and ensures that credentials for different users produce different tokens.
@@ -556,13 +556,14 @@ describe('actionsRegistryServiceFactory', () => {
input: {
name: 'test',
},
credentials: {
credentials: expect.objectContaining({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: {
type: 'service',
subject: 'user:default/mock',
},
},
}),
logger: expect.anything(),
});
});
@@ -14,10 +14,12 @@
* limitations under the License.
*/
import { mockCredentials } from '@backstage/backend-test-utils';
import {
createCredentialsWithNonePrincipal,
createCredentialsWithServicePrincipal,
createCredentialsWithUserPrincipal,
toInternalBackstageCredentials,
} from './helpers';
describe('credentials', () => {
@@ -82,6 +84,51 @@ describe('credentials', () => {
).not.toMatch(/my-token/);
});
it('should convert mock credentials to internal form', () => {
expect(
toInternalBackstageCredentials(mockCredentials.none()),
).toMatchObject({ version: 'v1', principal: { type: 'none' } });
expect(
toInternalBackstageCredentials(mockCredentials.user()),
).toMatchObject({
version: 'v1',
token: mockCredentials.user.token(),
principal: { type: 'user', userEntityRef: 'user:default/mock' },
});
expect(
toInternalBackstageCredentials(
mockCredentials.user('user:default/other'),
),
).toMatchObject({
version: 'v1',
token: mockCredentials.user.token('user:default/other'),
principal: { type: 'user', userEntityRef: 'user:default/other' },
});
expect(
toInternalBackstageCredentials(mockCredentials.limitedUser()),
).toMatchObject({
version: 'v1',
principal: { type: 'user', userEntityRef: 'user:default/mock' },
});
expect(
toInternalBackstageCredentials(mockCredentials.service()),
).toMatchObject({
version: 'v1',
principal: { type: 'service', subject: 'external:test-service' },
});
expect(
toInternalBackstageCredentials(mockCredentials.service('plugin:other')),
).toMatchObject({
version: 'v1',
principal: { type: 'service', subject: 'plugin:other' },
});
});
it('should have a serializable form both as strings and as JSON', () => {
const simpleService = createCredentialsWithServicePrincipal('my-service');
expect(String(simpleService)).toMatchInlineSnapshot(
@@ -20,6 +20,7 @@ describe('mockCredentials', () => {
it('creates a mocked credentials object for a none principal', () => {
expect(mockCredentials.none()).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'none' },
});
});
@@ -27,11 +28,13 @@ describe('mockCredentials', () => {
it('creates a mocked credentials object for a user principal', () => {
expect(mockCredentials.user()).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'user', userEntityRef: 'user:default/mock' },
});
expect(mockCredentials.user('user:default/other')).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'user', userEntityRef: 'user:default/other' },
});
});
@@ -39,11 +42,13 @@ describe('mockCredentials', () => {
it('creates a mocked credentials object for a limited user principal', () => {
expect(mockCredentials.limitedUser()).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'user', userEntityRef: 'user:default/mock' },
});
expect(mockCredentials.limitedUser('user:default/other')).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'user', userEntityRef: 'user:default/other' },
});
});
@@ -51,11 +56,13 @@ describe('mockCredentials', () => {
it('creates a mocked credentials object for a service principal', () => {
expect(mockCredentials.service()).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'service', subject: 'external:test-service' },
});
expect(mockCredentials.service('plugin:other')).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'service', subject: 'plugin:other' },
});
});
@@ -138,6 +145,7 @@ describe('mockCredentials', () => {
mockCredentials.service('test', { permissionNames: ['do.it'] }),
).toEqual({
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: {
type: 'service',
subject: 'test',
@@ -78,6 +78,7 @@ export namespace mockCredentials {
export function none(): BackstageCredentials<BackstageNonePrincipal> {
const result = {
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: { type: 'none' },
} as const;
Object.defineProperties(result, {
@@ -122,6 +123,7 @@ export namespace mockCredentials {
validateUserEntityRef(userEntityRef);
const result = {
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: {
type: 'user',
userEntityRef,
@@ -142,7 +144,10 @@ export namespace mockCredentials {
token: {
enumerable: false,
configurable: true,
value: user.token(),
value:
userEntityRef !== DEFAULT_MOCK_USER_ENTITY_REF || options?.actor
? user.token(userEntityRef, options)
: user.token(),
},
});
return result;
@@ -250,6 +255,7 @@ export namespace mockCredentials {
): BackstageCredentials<BackstageServicePrincipal> {
const result = {
$$type: '@backstage/BackstageCredentials',
version: 'v1',
principal: {
type: 'service',
subject,