Skip to content

Commit

Permalink
Update EnvironmentVariableCreate for multiple environments, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
khamilowicz committed Sep 27, 2024
1 parent dcf1d99 commit 6d52cf8
Show file tree
Hide file tree
Showing 9 changed files with 585 additions and 144 deletions.
27 changes: 26 additions & 1 deletion packages/eas-cli/graphql.schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,354 @@
import { Config } from '@oclif/core';

import { getMockAppFragment } from '../../../__tests__/commands/utils';
import { ExpoGraphqlClient } from '../../../commandUtils/context/contextUtils/createGraphqlClient';
import { testProjectId } from '../../../credentials/__tests__/fixtures-constants';
import {
EnvironmentSecretType,
EnvironmentVariableEnvironment,
EnvironmentVariableScope,
EnvironmentVariableVisibility,
} from '../../../graphql/generated';
import { EnvironmentVariableMutation } from '../../../graphql/mutations/EnvironmentVariableMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { EnvironmentVariablesQuery } from '../../../graphql/queries/EnvironmentVariablesQuery';
import {
promptVariableEnvironmentAsync,
promptVariableNameAsync,
promptVariableValueAsync,
} from '../../../utils/prompts';
import EnvironmentVariableCreate from '../create';

jest.mock('../../../graphql/mutations/EnvironmentVariableMutation');
jest.mock('../../../graphql/queries/AppQuery');
jest.mock('../../../graphql/queries/EnvironmentVariablesQuery');
jest.mock('../../../utils/prompts');

describe(EnvironmentVariableCreate, () => {
const graphqlClient = {} as any as ExpoGraphqlClient;
const mockConfig = {} as unknown as Config;
const variableId = 'testId';
const testAccountId = 'test-account-id';

beforeEach(() => {
jest.resetAllMocks();
jest.mocked(AppQuery.byIdAsync).mockImplementation(async () => getMockAppFragment());
jest
.mocked(EnvironmentVariableMutation.createForAppAsync)
.mockImplementation(async (_client, input, _appId) => ({
...input,
id: variableId,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
scope: EnvironmentVariableScope.Project,
}));
jest
.mocked(EnvironmentVariableMutation.createSharedVariableAsync)
.mockImplementation(async (_client, input, _appId) => ({
...input,
id: variableId,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
scope: EnvironmentVariableScope.Shared,
}));
jest
.mocked(EnvironmentVariableMutation.updateAsync)
.mockImplementation(async (_client, input) => ({
...input,
id: variableId,
name: 'VarName',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
scope: EnvironmentVariableScope.Shared,
}));
jest.mocked(EnvironmentVariablesQuery.byAppIdAsync).mockImplementation(async () => []);
jest.mocked(EnvironmentVariablesQuery.sharedAsync).mockImplementation(async () => []);
});

describe('in interactive mode', () => {
it('creates a project variable', async () => {
const command = new EnvironmentVariableCreate(
['--name', 'VarName', '--value', 'VarValue', '--environment', 'production'],
mockConfig
);

// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue({
loggedIn: { graphqlClient },
privateProjectConfig: { projectId: testProjectId },
});

await command.runAsync();

expect(EnvironmentVariableMutation.createForAppAsync).toHaveBeenCalledWith(
graphqlClient,
{
name: 'VarName',
value: 'VarValue',
environments: [EnvironmentVariableEnvironment.Production],
visibility: EnvironmentVariableVisibility.Public,
type: EnvironmentSecretType.String,
},
testProjectId
);
});

it('updates an existing variable in the same environment', async () => {
const command = new EnvironmentVariableCreate(
['--name', 'VarName', '--value', 'VarValue', '--environment', 'production'],
mockConfig
);

// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue({
loggedIn: { graphqlClient },
privateProjectConfig: { projectId: testProjectId },
});

const otherVariableId = 'otherId';

jest
.mocked(EnvironmentVariablesQuery.byAppIdAsync)
// @ts-expect-error
.mockImplementation(async () => [
{
id: otherVariableId,
environments: [EnvironmentVariableEnvironment.Production],
scope: EnvironmentVariableScope.Project,
},
]);

// @ts-expect-error
jest.spyOn(command, 'promptForOverwriteAsync').mockResolvedValue(true);
jest
.mocked(EnvironmentVariableMutation.updateAsync)
// @ts-expect-error
.mockImplementation(async (_client, input) => ({
...input,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
scope: EnvironmentVariableScope.Project,
}));

await command.runAsync();

expect(EnvironmentVariablesQuery.byAppIdAsync).toHaveBeenCalledWith(graphqlClient, {
appId: testProjectId,
filterNames: ['VarName'],
});

expect(EnvironmentVariableMutation.updateAsync).toHaveBeenCalledWith(graphqlClient, {
id: otherVariableId,
name: 'VarName',
value: 'VarValue',
environments: [EnvironmentVariableEnvironment.Production],
visibility: EnvironmentVariableVisibility.Public,
});
});

it('creates a shared variable', async () => {
const command = new EnvironmentVariableCreate(
[
'--name',
'VarName',
'--value',
'VarValue',
'--environment',
'production',
'--scope',
'shared',
],
mockConfig
);

// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue({
loggedIn: { graphqlClient },
privateProjectConfig: { projectId: testProjectId },
});

await command.runAsync();

expect(EnvironmentVariableMutation.createSharedVariableAsync).toHaveBeenCalledWith(
graphqlClient,
{
name: 'VarName',
value: 'VarValue',
environments: [EnvironmentVariableEnvironment.Production],
visibility: EnvironmentVariableVisibility.Public,
type: EnvironmentSecretType.String,
},
'test-account-id'
);
});

it('throws if a shared variable already exists', async () => {
const command = new EnvironmentVariableCreate(
[
'--name',
'VarName',
'--value',
'VarValue',
'--environment',
'production',
'--scope',
'shared',
],
mockConfig
);

// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue({
loggedIn: { graphqlClient },
privateProjectConfig: { projectId: testProjectId },
});

jest
.mocked(EnvironmentVariablesQuery.sharedAsync)
// @ts-expect-error
.mockImplementation(async () => [
{
id: 'otherId',
environments: [EnvironmentVariableEnvironment.Production],
scope: EnvironmentVariableScope.Shared,
},
]);

await expect(command.runAsync()).rejects.toThrow();
});

it('updates if a shared variable already exists and --force flag is set', async () => {
const command = new EnvironmentVariableCreate(
[
'--name',
'VarName',
'--value',
'VarValue',
'--environment',
'production',
'--force',
'--scope',
'shared',
],
mockConfig
);

const otherVariableId = 'otherId';

// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue({
loggedIn: { graphqlClient },
privateProjectConfig: { projectId: testProjectId },
});

jest
.mocked(EnvironmentVariablesQuery.sharedAsync)
// @ts-expect-error
.mockImplementation(async () => [
{
id: otherVariableId,
environments: [EnvironmentVariableEnvironment.Production],
scope: EnvironmentVariableScope.Shared,
},
]);

await command.runAsync();

expect(EnvironmentVariableMutation.updateAsync).toHaveBeenCalledWith(graphqlClient, {
id: otherVariableId,
name: 'VarName',
value: 'VarValue',
environments: [EnvironmentVariableEnvironment.Production],
visibility: EnvironmentVariableVisibility.Public,
});
});

it('creates a shared variable and links it', async () => {
const command = new EnvironmentVariableCreate(
[
'--name',
'VarName',
'--value',
'VarValue',
'--environment',
'production',
'--environment',
'development',
'--scope',
'shared',
'--link',
],
mockConfig
);

// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue({
loggedIn: { graphqlClient },
privateProjectConfig: { projectId: testProjectId },
});

await command.runAsync();

expect(EnvironmentVariableMutation.createSharedVariableAsync).toHaveBeenCalledWith(
graphqlClient,
{
name: 'VarName',
value: 'VarValue',
environments: [
EnvironmentVariableEnvironment.Production,
EnvironmentVariableEnvironment.Development,
],
visibility: EnvironmentVariableVisibility.Public,
type: EnvironmentSecretType.String,
},
testAccountId
);
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
graphqlClient,
'testId',
testProjectId,
EnvironmentVariableEnvironment.Production
);
expect(EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync).toHaveBeenCalledWith(
graphqlClient,
'testId',
testProjectId,
EnvironmentVariableEnvironment.Development
);
});

it('prompts for missing arguments', async () => {
const command = new EnvironmentVariableCreate([], mockConfig);

jest.mocked(promptVariableNameAsync).mockImplementation(async () => 'VarName');
jest.mocked(promptVariableValueAsync).mockImplementation(async () => 'VarValue');
jest
.mocked(promptVariableEnvironmentAsync)
// @ts-expect-error
.mockImplementation(async () => [EnvironmentVariableEnvironment.Production]);

// @ts-expect-error
jest.spyOn(command, 'getContextAsync').mockReturnValue({
loggedIn: { graphqlClient },
privateProjectConfig: { projectId: testProjectId },
});

await command.runAsync();

expect(promptVariableNameAsync).toHaveBeenCalled();
expect(promptVariableValueAsync).toHaveBeenCalled();
expect(promptVariableEnvironmentAsync).toHaveBeenCalled();
expect(EnvironmentVariableMutation.createForAppAsync).toHaveBeenCalledWith(
graphqlClient,
{
name: 'VarName',
value: 'VarValue',
environments: [EnvironmentVariableEnvironment.Production],
visibility: EnvironmentVariableVisibility.Public,
type: EnvironmentSecretType.String,
},
testProjectId
);
});
});
});
Loading

0 comments on commit 6d52cf8

Please sign in to comment.