Skip to content

Commit

Permalink
Revert "test: remove test reliance on file system"
Browse files Browse the repository at this point in the history
This reverts commit 8680e02.
  • Loading branch information
ChristopherPHolder committed Feb 20, 2024
1 parent 8680e02 commit d4214ef
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 148 deletions.
3 changes: 1 addition & 2 deletions packages/cli/src/lib/commands/init/command-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {handleFlowGeneration} from "./processes/generate-userflow";
import {handleGhWorkflowGeneration} from "./processes/generate-workflow";
import {handleBudgetsGeneration} from "./processes/generate-lh-budgets";
import {SETUP_CONFIRM_MESSAGE} from "./constants";
import { fileSystemManager } from '../../core/file';

export async function runInitCommand(argv: RcJsonAsArgv) {
const { interactive } = getGlobalOptionsFromArgv(argv);
Expand All @@ -20,7 +19,7 @@ export async function runInitCommand(argv: RcJsonAsArgv) {
await run([
collectRcJson,
updateRcJson,
handleFlowGeneration({ interactive: !!interactive, generateFlow }, fileSystemManager),
handleFlowGeneration({ interactive: !!interactive, generateFlow }),
handleGhWorkflowGeneration({ generateGhWorkflow }),
handleBudgetsGeneration({ generateBudgets, lhr }),
])(cfg );
Expand Down
13 changes: 11 additions & 2 deletions packages/cli/src/lib/commands/init/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { YargsCommandObject } from '../../core/yargs/types';
import { logVerbose } from '../../core/loggin';
import { log, logVerbose } from '../../core/loggin';
import { INIT_OPTIONS } from './options';
import { runInitCommand } from './command-impl';
import { getInitCommandOptionsFromArgv } from './utils';
import { collectRcJson } from './processes/collect-rc-json';
import { run } from '../../core/processing/behaviors';
import { SETUP_CONFIRM_MESSAGE } from './constants';
import { updateRcJson } from './processes/update-rc-json';
import { handleFlowGeneration } from './processes/generate-userflow';
import { getGlobalOptionsFromArgv } from '../../global/utils';
import { handleGhWorkflowGeneration } from './processes/generate-workflow';
import { handleBudgetsGeneration } from './processes/generate-lh-budgets';
import {runInitCommand} from "./command-impl";

export const initCommand: YargsCommandObject = {
command: 'init',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { INITIATED_PRJ_CFG, INITIATED_RC_JSON, EMPTY_PRJ_CFG } from 'test-data';
import { handleFlowGeneration } from './generate-userflow';
import { existsSync } from 'fs';
import { join } from 'path';
import { withUserFlowProject } from '@push-based/user-flow-cli-testing';

let originalCwd = process.cwd();

describe('generate userflow', () => {

/**
* Legend:
* - [nf] - flow file does not exist
* - [f] - flow file does exist
* - [F] - flow file creation
* - [nF] - no flow file creation
* - [P] - Prompt executes
* - [L] - Log occurs
* - [N] - no operation
*
* Cases:
* [nf] init --interactive => [P]: "Setup user flow" -> Y:[F]/n[nF],
* [f] init --interactive => [L]: "File already here"; [nF]
* [nf] init --no-interactive => [N]
* [f] init --no-interactive => [N]
* [nf] init --interactive --generateFlow => [L]: "File already here"; [nF]
* [f] init --interactive --generateFlow => [F]
* [f] init --interactive --no-generateFlow => [N]
*
*/

beforeAll(() => {
process.chdir(INITIATED_PRJ_CFG.root);
});
afterAll(() => {
process.chdir(originalCwd);
});

/*
@TODO create a test helper for functions with prompt side effects
// [nf] init --interactive => [P]: "Setup user flow" -> Y:[F]/n[nF]
it('should prompt with --interactive', withUserFlowProject(EMPTY_PRJ_CFG, async (_) => {
const expectedFilePath = join(INITIATED_PRJ_CFG.root, INITIATED_RC_JSON.collect.ufPath,'basic-navigation.uf.ts');
expect(existsSync(expectedFilePath)).toBeFalsy();
let o = '';
(console as any).log = (...v) => o += v.join(', ')
await handleFlowGeneration({interactive: true})(INITIATED_RC_JSON);
expect(o).toContain('Setup user flow')
expect(existsSync(expectedFilePath)).toBeTruthy();
})
);*/

// [f] init --interactive => [L]: "File already here"; [nF]
it('should not prompt with --interactive if file exists', withUserFlowProject(INITIATED_PRJ_CFG, async () => {
const expectedFilePath = join(INITIATED_PRJ_CFG.root, INITIATED_RC_JSON.collect.ufPath,'basic-navigation.uf.ts');
expect(existsSync(expectedFilePath)).toBeTruthy();
await handleFlowGeneration({interactive: true})(INITIATED_RC_JSON);
expect(existsSync(expectedFilePath)).toBeTruthy();
}));

// [f] init --no-interactive => [N]
it('should not prompt with --no-interactive if file exists', withUserFlowProject(INITIATED_PRJ_CFG, async () => {
const expectedFilePath = join(INITIATED_PRJ_CFG.root, INITIATED_RC_JSON.collect.ufPath,'basic-navigation.uf.ts');
expect(existsSync(expectedFilePath)).toBeTruthy();
await handleFlowGeneration({interactive: false})(INITIATED_RC_JSON);
expect(existsSync(expectedFilePath)).toBeTruthy();
}));

// [nf] init --no-interactive => [N]
it('should not prompt with --no-interactive if file does not exists', withUserFlowProject(EMPTY_PRJ_CFG, async () => {
const expectedFilePath = join(INITIATED_PRJ_CFG.root, INITIATED_RC_JSON.collect.ufPath,'basic-navigation.uf.ts');
expect(existsSync(expectedFilePath)).toBeFalsy();
await handleFlowGeneration({interactive: false})(INITIATED_RC_JSON);
expect(existsSync(expectedFilePath)).toBeFalsy();
}));

// [nf] init --interactive --generateFlow => [L]: "File already here"; [nF]
it('should create flow when --generateFlow is used', withUserFlowProject(EMPTY_PRJ_CFG, async () => {
const expectedFilePath = join(INITIATED_PRJ_CFG.root, INITIATED_RC_JSON.collect.ufPath,'basic-navigation.uf.ts');
expect(existsSync(expectedFilePath)).toBeFalsy();
await handleFlowGeneration({interactive: true, generateFlow: true})(INITIATED_RC_JSON);
expect(existsSync(expectedFilePath)).toBeTruthy();
}));

// [f] init --interactive --no-generateFlow => [N]
it('should not create flow when --no-generateFlow is used', withUserFlowProject(EMPTY_PRJ_CFG, async () => {
const expectedFilePath = join(INITIATED_PRJ_CFG.root, INITIATED_RC_JSON.collect.ufPath,'basic-navigation.uf.ts');
expect(existsSync(expectedFilePath)).toBeFalsy();
await handleFlowGeneration({interactive: true, generateFlow: false})(INITIATED_RC_JSON);
expect(existsSync(expectedFilePath)).toBeFalsy();
}));

});
67 changes: 30 additions & 37 deletions packages/cli/src/lib/commands/init/processes/generate-userflow.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { RcJson } from '../../../types';
import { join } from 'path';
import { FileSystemManager } from '../../../core/file';
import { log, logVerbose } from '../../../core/loggin';
import { readFile, writeFile } from '../../../core/file';
import { log } from '../../../core/loggin';
import { mkdirSync, readdirSync } from 'fs';
import { FlowExampleMap } from '../constants';
import { FlowExamples } from '../types';
import { ifThenElse } from '../../../core/processing/behaviors';
import { askToSkip } from '../../../core/prompt';
import { CLIProcess } from '../../../core/processing/types';
import { logVerbose } from '../../../core/loggin';
import { PROMPT_INIT_GENERATE_FLOW } from '../options/generateFlow.constants';

const exampleName = 'basic-navigation';
Expand All @@ -16,53 +18,44 @@ export function getExamplePathDest(flowExample: FlowExamples, folder: string): s
return join(folder, fileName);
}

export const userflowIsNotCreated = (fSM: FileSystemManager) => {
return (cfg: RcJson): Promise<boolean> => {
const path = getExamplePathDest(exampleName, cfg.collect.ufPath);
return Promise.resolve(!fSM.existSync(path));
export const userflowIsNotCreated = (cfg?: RcJson) => Promise.resolve(cfg ? readFile(getExamplePathDest(exampleName, cfg.collect.ufPath)) === '' : false);

export async function generateUserFlow(cliCfg: RcJson): Promise<RcJson> {
const ufPath = cliCfg.collect.ufPath;
// DX create directory if it does ot exist
try {
readdirSync(ufPath);
} catch (e) {
mkdirSync(ufPath, { recursive: true });
}
};
const tplFileName = FlowExampleMap[exampleName];
const exampleSourceLocation = join(__dirname,'..', 'static', tplFileName);
const exampleDestination = join(ufPath, tplFileName);

export const generateUserFlow = (fSM: FileSystemManager): CLIProcess => {
return (cfg: RcJson): Promise<RcJson> => {
const ufPath = cfg.collect.ufPath;
// DX create directory if it does ot exist
try {
fSM.readdirSync(ufPath);
} catch (e) {
fSM.mkdirSync(ufPath, { recursive: true });
}
const tplFileName = FlowExampleMap[exampleName];
const exampleSourceLocation = join(__dirname, '..', 'static', tplFileName);
const exampleDestination = join(ufPath, tplFileName);
if (readFile(exampleDestination) !== '') {
logVerbose(`User flow ${exampleName} already generated under ${exampleDestination}.`);
return Promise.resolve(cliCfg);
}

if (fSM.readFile(exampleDestination) !== '') {
logVerbose(`User flow ${exampleName} already generated under ${exampleDestination}.`);
return Promise.resolve(cfg);
}
const fileContent = fSM.readFile(exampleSourceLocation, { fail: true }).toString();
fSM.writeFile(exampleDestination, fileContent);
const fileContent = readFile(exampleSourceLocation, { fail: true }).toString();
writeFile(exampleDestination, fileContent);

log(`setup user-flow for basic navigation in ${ufPath} successfully`);
return Promise.resolve(cfg);
}
};
log(`setup user-flow for basic navigation in ${ufPath} successfully`);
return Promise.resolve(cliCfg);
}

export function handleFlowGeneration(
{ generateFlow, interactive }: {interactive: boolean, generateFlow?: boolean},
fSM: FileSystemManager
): CLIProcess {
export function handleFlowGeneration({ generateFlow, interactive }: {interactive: boolean, generateFlow?: boolean}): CLIProcess {
return ifThenElse(
// if `withFlow` is not used in the CLI is in interactive mode
() => interactive && generateFlow === undefined,
() => interactive == true && generateFlow === undefined,
// Prompt for flow generation
askToSkip(PROMPT_INIT_GENERATE_FLOW, generateUserFlow(fSM),
askToSkip(PROMPT_INIT_GENERATE_FLOW, generateUserFlow,
// if the flow is not created already, otherwise skip creation
{ precondition: userflowIsNotCreated(fSM) }),
{ precondition: userflowIsNotCreated }),
// else `withFlow` is used and true
ifThenElse(() => !!generateFlow,
// generate the file => else do nothing
generateUserFlow(fSM))
generateUserFlow)
)
}

This file was deleted.

15 changes: 3 additions & 12 deletions packages/cli/src/lib/core/file/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { dirname } from 'path';
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs';
import { existsSync, readFileSync, writeFileSync, mkdirSync, lstatSync } from 'fs';
import { logVerbose } from '../loggin';
import { formatCode, getParserFromExtname } from '../prettier';
import { getParserFromExtname, formatCode } from '../prettier';
import { ReadFileConfig } from '../../commands/collect/utils/replay/types';
import { ExtToOutPut, ResolveFileResult } from './types';

Expand Down Expand Up @@ -61,7 +61,7 @@ export function readFile<R extends any = undefined, T extends ReadFileConfig = {
/**
* Ensures the folder exists before writing it
*/
export function writeFile(filePath: string, data: string): void {
export function writeFile(filePath: string, data: string) {
const dir = dirname(filePath);
if (!existsSync(dir)) {
logVerbose(`Created dir ${dir} to save ${filePath}`);
Expand Down Expand Up @@ -101,12 +101,3 @@ export function resolveAnyFile<T>(path: string): ResolveFileResult<T> {
return { exports, path };
}

export const fileSystemManager = {
writeFile: writeFile,
readFile: readFile,
existSync: existsSync,
readdirSync: readdirSync,
mkdirSync: mkdirSync,
}

export type FileSystemManager = typeof fileSystemManager;
2 changes: 1 addition & 1 deletion packages/cli/src/lib/core/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function askToSkip(
question: string,
cliProcess: CLIProcess,
options: {
precondition?: (r: RcJson) => Promise<boolean>;
precondition?: (r?: RcJson) => Promise<boolean>;
} = {
precondition: async () => true,
}
Expand Down

0 comments on commit d4214ef

Please sign in to comment.