mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
650 lines
21 KiB
TypeScript
650 lines
21 KiB
TypeScript
import { pick } from "@hexclave/shared/dist/utils/objects";
|
|
import { describe } from "vitest";
|
|
import { it } from "../helpers";
|
|
import { createApp } from "./js-helpers";
|
|
|
|
|
|
describe("access control", () => {
|
|
it("serverApp project does not have config methods", async ({ expect }) => {
|
|
const { serverApp } = await createApp();
|
|
const project = await serverApp.getProject();
|
|
|
|
// Server apps only get basic Project type, not AdminProject
|
|
// So config methods should not exist
|
|
expect((project as any).updateConfig).toBeUndefined();
|
|
expect((project as any).pushConfig).toBeUndefined();
|
|
expect((project as any).updatePushedConfig).toBeUndefined();
|
|
expect((project as any).getConfig).toBeUndefined();
|
|
});
|
|
|
|
it("clientApp project does not have config methods", async ({ expect }) => {
|
|
const { clientApp } = await createApp();
|
|
const project = await clientApp.getProject();
|
|
|
|
// Client apps only get basic Project type, not AdminProject
|
|
// So config methods should not exist
|
|
expect((project as any).updateConfig).toBeUndefined();
|
|
expect((project as any).pushConfig).toBeUndefined();
|
|
expect((project as any).updatePushedConfig).toBeUndefined();
|
|
expect((project as any).getConfig).toBeUndefined();
|
|
});
|
|
|
|
it("only adminApp project has config methods", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// AdminApp gets AdminProject which has config methods
|
|
expect(typeof project.updateConfig).toBe('function');
|
|
expect(typeof project.pushConfig).toBe('function');
|
|
expect(typeof project.updatePushedConfig).toBe('function');
|
|
expect(typeof project.getConfig).toBe('function');
|
|
});
|
|
});
|
|
|
|
|
|
describe("error handling", () => {
|
|
it("updateConfig rejects non-existent config fields", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
await expect(project.updateConfig({
|
|
'nonExistentField.value': true,
|
|
} as any)).rejects.toThrow(/nonExistentField/);
|
|
});
|
|
|
|
it("pushConfig rejects non-existent config fields", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
await expect(project.pushConfig({
|
|
'nonExistentField.value': true,
|
|
} as any, { source: { type: "unlinked" } })).rejects.toThrow(/nonExistentField/);
|
|
});
|
|
|
|
it("updateConfig rejects invalid oauth provider type", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
await expect(project.updateConfig({
|
|
'auth.oauth.providers.invalid': {
|
|
type: 'not-a-real-provider',
|
|
isShared: false,
|
|
clientId: 'test',
|
|
clientSecret: 'test',
|
|
allowSignIn: true,
|
|
allowConnectedAccounts: true,
|
|
},
|
|
} as any)).rejects.toThrow(/type must be one of the following values/);
|
|
});
|
|
|
|
it("pushConfig rejects environment-only fields at branch level", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// pushConfig uses branch level, which doesn't allow environment-only fields
|
|
// like clientId, clientSecret, isShared
|
|
await expect(project.pushConfig({
|
|
'auth.oauth.providers.google': {
|
|
type: 'google',
|
|
isShared: false,
|
|
clientId: 'test-client-id',
|
|
clientSecret: 'test-secret',
|
|
allowSignIn: true,
|
|
allowConnectedAccounts: true,
|
|
},
|
|
} as any, { source: { type: "unlinked" } })).rejects.toThrow(/auth\.oauth\.providers/);
|
|
});
|
|
|
|
it("pushConfig allows branch-level oauth fields", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Branch-level fields only (no secrets)
|
|
await project.pushConfig({
|
|
'auth.oauth.providers.my_provider': {
|
|
type: 'google',
|
|
allowSignIn: true,
|
|
allowConnectedAccounts: true,
|
|
},
|
|
} as any, { source: { type: "unlinked" } });
|
|
|
|
const config = await project.getConfig();
|
|
expect(config.auth.oauth.providers['my_provider']).toBeDefined();
|
|
});
|
|
});
|
|
|
|
|
|
describe("getConfig", () => {
|
|
it("gets config", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
const config = await project.getConfig();
|
|
expect(pick(config, ["auth", "users", "teams"])).toMatchInlineSnapshot(`
|
|
{
|
|
"auth": {
|
|
"allowSignUp": true,
|
|
"oauth": {
|
|
"accountMergeStrategy": "link_method",
|
|
"providers": {},
|
|
},
|
|
"otp": { "allowSignIn": false },
|
|
"passkey": { "allowSignIn": false },
|
|
"password": { "allowSignIn": true },
|
|
"signUpRules": {},
|
|
"signUpRulesDefaultAction": "allow",
|
|
},
|
|
"teams": {
|
|
"allowClientTeamCreation": false,
|
|
"createPersonalTeamOnSignUp": false,
|
|
},
|
|
"users": { "allowClientUserDeletion": false },
|
|
}
|
|
`);
|
|
});
|
|
});
|
|
|
|
|
|
describe("updateConfig", () => {
|
|
it("updates config at environment level", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
const config = await project.getConfig();
|
|
expect(config['auth']).toMatchInlineSnapshot(`
|
|
{
|
|
"allowSignUp": true,
|
|
"oauth": {
|
|
"accountMergeStrategy": "link_method",
|
|
"providers": {},
|
|
},
|
|
"otp": { "allowSignIn": false },
|
|
"passkey": { "allowSignIn": false },
|
|
"password": { "allowSignIn": true },
|
|
"signUpRules": {},
|
|
"signUpRulesDefaultAction": "allow",
|
|
}
|
|
`);
|
|
|
|
await project.updateConfig({
|
|
'auth.allowSignUp': false,
|
|
});
|
|
|
|
const config2 = await project.getConfig();
|
|
expect(config2['auth']).toMatchInlineSnapshot(`
|
|
{
|
|
"allowSignUp": false,
|
|
"oauth": {
|
|
"accountMergeStrategy": "link_method",
|
|
"providers": {},
|
|
},
|
|
"otp": { "allowSignIn": false },
|
|
"passkey": { "allowSignIn": false },
|
|
"password": { "allowSignIn": true },
|
|
"signUpRules": {},
|
|
"signUpRulesDefaultAction": "allow",
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("updateConfig merges with existing config", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Set first value
|
|
await project.updateConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
});
|
|
|
|
// Set second value
|
|
await project.updateConfig({
|
|
'users.allowClientUserDeletion': true,
|
|
});
|
|
|
|
// Both should be set
|
|
const config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
expect(config.users.allowClientUserDeletion).toBe(true);
|
|
});
|
|
});
|
|
|
|
|
|
describe("pushConfig", () => {
|
|
it("pushConfig sets branch-level config", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push config
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
'teams.createPersonalTeamOnSignUp': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// Verify config is applied
|
|
const config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
expect(config.teams.createPersonalTeamOnSignUp).toBe(true);
|
|
});
|
|
|
|
it("pushConfig replaces previous pushConfig", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push first config
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
'teams.createPersonalTeamOnSignUp': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// Verify first config is applied
|
|
let config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
expect(config.teams.createPersonalTeamOnSignUp).toBe(true);
|
|
|
|
// Push second config (completely replaces first)
|
|
await project.pushConfig({
|
|
'auth.passkey.allowSignIn': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// Verify old values are gone (back to defaults) and new value is set
|
|
config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(false); // back to default
|
|
expect(config.teams.createPersonalTeamOnSignUp).toBe(false); // back to default
|
|
expect(config.auth.passkey.allowSignIn).toBe(true); // new value
|
|
});
|
|
|
|
it("updateConfig takes precedence over pushConfig", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push config first
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// Verify push is applied
|
|
let config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
|
|
// updateConfig overrides the same value
|
|
await project.updateConfig({
|
|
'teams.allowClientTeamCreation': false,
|
|
});
|
|
|
|
// Environment-level (updateConfig) takes precedence
|
|
config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(false);
|
|
});
|
|
|
|
it("pushConfig does not affect updateConfig values", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// updateConfig sets environment-level value
|
|
await project.updateConfig({
|
|
'users.allowClientUserDeletion': true,
|
|
});
|
|
|
|
// pushConfig sets branch-level values
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// Both should be present
|
|
let config = await project.getConfig();
|
|
expect(config.users.allowClientUserDeletion).toBe(true); // from updateConfig
|
|
expect(config.teams.allowClientTeamCreation).toBe(true); // from pushConfig
|
|
|
|
// Push new config (replaces branch but not environment)
|
|
await project.pushConfig({
|
|
'auth.passkey.allowSignIn': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// updateConfig value should still be there
|
|
config = await project.getConfig();
|
|
expect(config.users.allowClientUserDeletion).toBe(true); // still from updateConfig
|
|
expect(config.teams.allowClientTeamCreation).toBe(false); // back to default (old push gone)
|
|
expect(config.auth.passkey.allowSignIn).toBe(true); // from new push
|
|
});
|
|
});
|
|
|
|
|
|
describe("updatePushedConfig", () => {
|
|
it("updatePushedConfig merges into pushed config", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push initial config
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// updatePushedConfig merges into the pushed config
|
|
await project.updatePushedConfig({
|
|
'teams.createPersonalTeamOnSignUp': true,
|
|
});
|
|
|
|
// Both values should be set
|
|
const config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
expect(config.teams.createPersonalTeamOnSignUp).toBe(true);
|
|
});
|
|
|
|
it("pushConfig replaces updatePushedConfig changes", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push initial config
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// updatePushedConfig adds a value
|
|
await project.updatePushedConfig({
|
|
'teams.createPersonalTeamOnSignUp': true,
|
|
});
|
|
|
|
// Verify both values are present
|
|
let config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
expect(config.teams.createPersonalTeamOnSignUp).toBe(true);
|
|
|
|
// pushConfig replaces everything including updatePushedConfig changes
|
|
await project.pushConfig({
|
|
'auth.passkey.allowSignIn': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
// Old values should be gone
|
|
config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(false); // back to default
|
|
expect(config.teams.createPersonalTeamOnSignUp).toBe(false); // back to default
|
|
expect(config.auth.passkey.allowSignIn).toBe(true); // new push value
|
|
});
|
|
|
|
it("updateConfig takes precedence over updatePushedConfig", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// updatePushedConfig sets a value at branch level
|
|
await project.updatePushedConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
});
|
|
|
|
// Verify value is applied
|
|
let config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
|
|
// updateConfig overrides at environment level
|
|
await project.updateConfig({
|
|
'teams.allowClientTeamCreation': false,
|
|
});
|
|
|
|
// Environment-level takes precedence
|
|
config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(false);
|
|
});
|
|
|
|
it("updatePushedConfig rejects environment-only fields", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// updatePushedConfig uses branch level, so environment-only fields should be rejected
|
|
await expect(project.updatePushedConfig({
|
|
'auth.oauth.providers.google': {
|
|
type: 'google',
|
|
isShared: false,
|
|
clientId: 'test-client-id',
|
|
clientSecret: 'test-secret',
|
|
allowSignIn: true,
|
|
allowConnectedAccounts: true,
|
|
},
|
|
} as any)).rejects.toThrow(/auth\.oauth\.providers/);
|
|
});
|
|
});
|
|
|
|
|
|
describe("resetConfigOverrideKeys", () => {
|
|
it("resetConfigOverrideKeys removes keys from environment override", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Set branch config
|
|
await project.updatePushedConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
});
|
|
|
|
// Set environment config that overrides branch
|
|
await project.updateConfig({
|
|
'teams.allowClientTeamCreation': false,
|
|
});
|
|
|
|
// Verify environment takes precedence
|
|
let config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(false);
|
|
|
|
// Reset the key from environment level
|
|
await project.resetConfigOverrideKeys("environment", ["teams.allowClientTeamCreation"]);
|
|
|
|
// Now branch config should win
|
|
config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
});
|
|
|
|
it("resetConfigOverrideKeys with parent key removes children", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Set environment config with multiple team settings
|
|
await project.updateConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
'teams.createPersonalTeamOnSignUp': true,
|
|
'users.allowClientUserDeletion': true,
|
|
});
|
|
|
|
// Reset the parent "teams" key
|
|
await project.resetConfigOverrideKeys("environment", ["teams"]);
|
|
|
|
// Verify teams keys are gone but users key remains
|
|
const envOverride = await project.getConfigOverride("environment");
|
|
expect(envOverride["teams.allowClientTeamCreation"]).toBeUndefined();
|
|
expect(envOverride["teams.createPersonalTeamOnSignUp"]).toBeUndefined();
|
|
expect(envOverride["users.allowClientUserDeletion"]).toBe(true);
|
|
});
|
|
|
|
it("resetConfigOverrideKeys with non-existent keys is a no-op", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Set environment config
|
|
await project.updateConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
});
|
|
|
|
// Reset a non-existent key
|
|
await project.resetConfigOverrideKeys("environment", ["nonExistent.key"]);
|
|
|
|
// Config should be unchanged
|
|
const envOverride = await project.getConfigOverride("environment");
|
|
expect(envOverride["teams.allowClientTeamCreation"]).toBe(true);
|
|
});
|
|
|
|
it("resetConfigOverrideKeys on branch level works", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Set branch config
|
|
await project.updatePushedConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
'users.allowClientUserDeletion': true,
|
|
});
|
|
|
|
// Reset one branch key
|
|
await project.resetConfigOverrideKeys("branch", ["teams.allowClientTeamCreation"]);
|
|
|
|
const branchOverride = await project.getConfigOverride("branch");
|
|
expect(branchOverride["teams.allowClientTeamCreation"]).toBeUndefined();
|
|
expect(branchOverride["users.allowClientUserDeletion"]).toBe(true);
|
|
});
|
|
});
|
|
|
|
|
|
describe("pushedConfigSource", () => {
|
|
it("getPushedConfigSource returns unlinked by default", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
const source = await project.getPushedConfigSource();
|
|
expect(source.type).toBe("unlinked");
|
|
});
|
|
|
|
it("pushConfig with source sets the source", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, {
|
|
source: {
|
|
type: "pushed-from-github",
|
|
owner: "myorg",
|
|
repo: "myrepo",
|
|
branch: "main",
|
|
commitHash: "abc123",
|
|
configFilePath: "stack.config.ts",
|
|
},
|
|
});
|
|
|
|
const source = await project.getPushedConfigSource();
|
|
expect(source.type).toBe("pushed-from-github");
|
|
if (source.type === "pushed-from-github") {
|
|
expect(source.owner).toBe("myorg");
|
|
expect(source.repo).toBe("myrepo");
|
|
expect(source.branch).toBe("main");
|
|
expect(source.commitHash).toBe("abc123");
|
|
expect(source.configFilePath).toBe("stack.config.ts");
|
|
}
|
|
});
|
|
|
|
it("pushConfig without source defaults to unlinked", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// First push with source
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, {
|
|
source: {
|
|
type: "pushed-from-github",
|
|
owner: "myorg",
|
|
repo: "myrepo",
|
|
branch: "main",
|
|
commitHash: "abc123",
|
|
configFilePath: "stack.config.ts",
|
|
},
|
|
});
|
|
|
|
// Then push without source (should default to unlinked)
|
|
await project.pushConfig({
|
|
'teams.createPersonalTeamOnSignUp': true,
|
|
}, { source: { type: "unlinked" } });
|
|
|
|
const source = await project.getPushedConfigSource();
|
|
expect(source.type).toBe("unlinked");
|
|
});
|
|
|
|
it("updatePushedConfig preserves the source", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push with GitHub source
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, {
|
|
source: {
|
|
type: "pushed-from-github",
|
|
owner: "myorg",
|
|
repo: "myrepo",
|
|
branch: "main",
|
|
commitHash: "abc123",
|
|
configFilePath: "stack.config.ts",
|
|
},
|
|
});
|
|
|
|
// Update pushed config
|
|
await project.updatePushedConfig({
|
|
'teams.createPersonalTeamOnSignUp': true,
|
|
});
|
|
|
|
// Source should still be GitHub
|
|
const source = await project.getPushedConfigSource();
|
|
expect(source.type).toBe("pushed-from-github");
|
|
});
|
|
|
|
it("unlinkPushedConfigSource sets source to unlinked", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push with GitHub source
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, {
|
|
source: {
|
|
type: "pushed-from-github",
|
|
owner: "myorg",
|
|
repo: "myrepo",
|
|
branch: "main",
|
|
commitHash: "abc123",
|
|
configFilePath: "stack.config.ts",
|
|
},
|
|
});
|
|
|
|
// Verify source is GitHub
|
|
expect((await project.getPushedConfigSource()).type).toBe("pushed-from-github");
|
|
|
|
// Unlink
|
|
await project.unlinkPushedConfigSource();
|
|
|
|
// Verify source is now unlinked
|
|
const source = await project.getPushedConfigSource();
|
|
expect(source.type).toBe("unlinked");
|
|
});
|
|
|
|
it("unlinkPushedConfigSource preserves the config", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
// Push config with source
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, {
|
|
source: {
|
|
type: "pushed-from-github",
|
|
owner: "myorg",
|
|
repo: "myrepo",
|
|
branch: "main",
|
|
commitHash: "abc123",
|
|
configFilePath: "stack.config.ts",
|
|
},
|
|
});
|
|
|
|
// Unlink
|
|
await project.unlinkPushedConfigSource();
|
|
|
|
// Config should still be there
|
|
const config = await project.getConfig();
|
|
expect(config.teams.allowClientTeamCreation).toBe(true);
|
|
});
|
|
|
|
it("can set pushed-from-unknown source", async ({ expect }) => {
|
|
const { adminApp } = await createApp();
|
|
const project = await adminApp.getProject();
|
|
|
|
await project.pushConfig({
|
|
'teams.allowClientTeamCreation': true,
|
|
}, {
|
|
source: { type: "pushed-from-unknown" },
|
|
});
|
|
|
|
const source = await project.getPushedConfigSource();
|
|
expect(source.type).toBe("pushed-from-unknown");
|
|
});
|
|
});
|