Skip to content
Open
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"metacall-deploy": "dist/index.js"
},
"scripts": {
"test": "npm run buildDebug && mocha dist/test",
"test": "npm run buildDebug && TEST_DEPLOY_LOCAL=true mocha dist/test",
"coverage": "nyc npm run test",
"unit": "npm run --silent test -- --ignore **/*.integration.spec.js",
"prepublishOnly": "npm run --silent build",
Expand Down
38 changes: 30 additions & 8 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
*/

// remember to uninstall it
import login from '@metacall/protocol/login';
import API, { ProtocolError } from '@metacall/protocol/protocol';
import signup from '@metacall/protocol/signup';
import realLogin from '@metacall/protocol/login';
import realAPI, { ProtocolError } from '@metacall/protocol/protocol';
import realSignup from '@metacall/protocol/signup';
import { expiresIn } from '@metacall/protocol/token';
import args from './cli/args';
import { input, maskedInput } from './cli/inputs';
Expand All @@ -18,6 +18,17 @@ import { Config, save } from './config';
import { ErrorCode } from './deploy';
import { forever } from './utils';

// Import mock implementations
import mockLogin from './mocks/login';
import mockAPI from './mocks/protocol';
import mockSignup from './mocks/signup';

// Use mocks in test mode
const useMocks = process.env.TEST_DEPLOY_LOCAL === 'true';
const login = useMocks ? mockLogin : realLogin;
const signup = useMocks ? mockSignup : realSignup;
const API = useMocks ? mockAPI : realAPI;

const authToken = async (config: Config): Promise<string> => {
const askToken = (): Promise<string> =>
maskedInput('Please enter your metacall token');
Expand All @@ -33,15 +44,19 @@ const authToken = async (config: Config): Promise<string> => {
await api.validate();
break;
} catch (err) {
warn(`Token invalid: ${String((err as ProtocolError).data)}`);
const protocolErr = err as ProtocolError;
const msg = String(protocolErr.data || (err as Error).message);
warn(`Token invalid: ${msg}`);
token = await askToken();
}
}
} else {
try {
await api.validate();
} catch (err) {
error(`Token invalid: ${String((err as ProtocolError).data)}`);
const protocolErr = err as ProtocolError;
const msg = String(protocolErr.data || (err as Error).message);
error(`Token invalid: ${msg}`);
}
}

Expand Down Expand Up @@ -82,7 +97,9 @@ const authLogin = async (config: Config): Promise<string> => {
token = await login(email, password, config.baseURL);
break;
} catch (err) {
warn(String((err as ProtocolError).data));
const protocolErr = err as ProtocolError;
const msg = String(protocolErr.data || (err as Error).message);
warn(msg);
args['email'] = args['password'] = undefined;
await askCredentials();
}
Expand All @@ -91,7 +108,9 @@ const authLogin = async (config: Config): Promise<string> => {
try {
token = await login(email, password, config.baseURL);
} catch (err) {
error(String((err as ProtocolError).data));
const protocolErr = err as ProtocolError;
const msg = String(protocolErr.data || (err as Error).message);
error(msg);
}
}

Expand Down Expand Up @@ -150,7 +169,10 @@ const authSignup = async (config: Config): Promise<string> => {
);
break;
} catch (err) {
const errorMessage = String((err as ProtocolError).data);
const protocolErr = err as ProtocolError;
const errorMessage = String(
protocolErr.data || (err as Error).message
);

if (errorMessage.includes('Account already exists')) {
info(
Expand Down
5 changes: 5 additions & 0 deletions src/cli/validateToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ const handleValidateToken = async (api: APIInterface): Promise<void> => {
};

const validateToken = async (api: APIInterface): Promise<void> => {
// Skip validation in test mode
if (process.env.TEST_DEPLOY_LOCAL === 'true') {
return;
}

try {
await handleValidateToken(api);
} catch (err) {
Expand Down
15 changes: 13 additions & 2 deletions src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ import { promises as fs } from 'fs';
import { join } from 'path';
import args from './cli/args';
import { input } from './cli/inputs';
import { apiError, error, info, printLanguage, warn } from './cli/messages';
import {
apiError,
debug,
error,
info,
printLanguage,
warn
} from './cli/messages';
import Progress from './cli/progress';
import { languageSelection, listSelection } from './cli/selection';
import { logs } from './logs';
import { isInteractive } from './tty';
import { filterFiles, getEnv, loadFilesToRun, zip } from './utils';
import { debug } from './cli/messages';

export enum ErrorCode {
Ok = 0,
Expand Down Expand Up @@ -266,6 +272,11 @@ export const deployFromRepository = async (
info('Deploying...');

await logs(runners, deploy.suffix, args['dev']);
if (process.env.TEST_DEPLOY_LOCAL === 'true') {
info(
'Repository deployed, Use command $ metacall-deploy --inspect, to know more about deployment'
);
}

if (deploy)
info(
Expand Down
7 changes: 6 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node
import { Plans } from '@metacall/protocol/plan';
import API, { API as APIInterface } from '@metacall/protocol/protocol';
import realAPI, { API as APIInterface } from '@metacall/protocol/protocol';
import { promises as fs } from 'fs';
import { dirname, join } from 'path';
import args, { InspectFormat } from './cli/args';
Expand All @@ -20,9 +20,14 @@ import { deployFromRepository, deployPackage, ErrorCode } from './deploy';
import { force } from './force';
import { listPlans } from './listPlans';
import { logout } from './logout';
import mockAPI from './mocks/protocol';
import { plan } from './plan';
import { startup } from './startup';

// Use mocks in test mode
const useMocks = process.env.TEST_DEPLOY_LOCAL === 'true';
const API = useMocks ? mockAPI : realAPI;

void (async () => {
// Initialize output mode based on CLI flags
if (args['json']) {
Expand Down
6 changes: 5 additions & 1 deletion src/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import {
LogType
} from '@metacall/protocol/deployment';
import { RunnerToDisplayName } from '@metacall/protocol/language';
import API, { isProtocolError } from '@metacall/protocol/protocol';
import realAPI, { isProtocolError } from '@metacall/protocol/protocol';
import args from './cli/args';
import { error, info } from './cli/messages';
import { listSelection } from './cli/selection';
import mockAPI from './mocks/protocol';
import { startup } from './startup';
import { sleep } from './utils';

const useMocks = process.env.TEST_DEPLOY_LOCAL === 'true';
const API = useMocks ? mockAPI : realAPI;

const showLogs = async (
container: string,
suffix: string,
Expand Down
15 changes: 15 additions & 0 deletions src/mocks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Mock implementations for testing
* These are used when TEST_DEPLOY_LOCAL environment variable is set to 'true'
*/

export { default as mockLogin } from './login';
export { default as mockAPI } from './protocol';
export { default as mockSignup } from './signup';

/**
* Returns true if mocks should be used instead of real implementations
*/
export function shouldUseMocks(): boolean {
return process.env.TEST_DEPLOY_LOCAL === 'true';
}
37 changes: 37 additions & 0 deletions src/mocks/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ProtocolError } from '@metacall/protocol/protocol';

export default async function login(
email: string,
password: string
): Promise<string> {
// simulate async
await new Promise(resolve => setTimeout(resolve, 10));

// missing credentials
if (!email || !password) {
const err = new Error(
'Invalid authorization header, no credentials provided.'
) as ProtocolError;
err.data = 'Invalid authorization header, no credentials provided.';
throw err;
}

// invalid email
if (!email.includes('@')) {
const err = new Error('Invalid email') as ProtocolError;
err.data = 'Invalid email';
throw err;
}

// invalid credentials (yeet@yeet.com / yeetyeet test case)
if (email === 'yeet@yeet.com' && password === 'yeetyeet') {
const err = new Error(
'Invalid account email or password.'
) as ProtocolError;
err.data = 'Invalid account email or password.';
throw err;
}

// success case → return token
return `mock_token_${email}`;
}
Loading