Skip to content
This repository has been archived by the owner on Jun 28, 2024. It is now read-only.

Commit

Permalink
feat: streamline playground detection. prepare for upcoming changes
Browse files Browse the repository at this point in the history
* playground detection is now more flexible
* upgrade to new play script format/concept
* update tests
  • Loading branch information
TheEdward162 committed Jan 14, 2021
1 parent 07f7b30 commit d3b6880
Show file tree
Hide file tree
Showing 7 changed files with 357 additions and 273 deletions.
3 changes: 3 additions & 0 deletions fixtures/playgrounds/pub-hours/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build
node_modules
package-lock.json
32 changes: 19 additions & 13 deletions fixtures/playgrounds/pub-hours/pub-hours.play.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import * as fs from 'fs';
import * as nodePath from 'path';
import { join as joinPath } from 'path';
import { promisify, inspect } from 'util';

import { Provider } from '@superfaceai/sdk';

// These types are exported from the ast, but not from the sdk
type ProfileDocumentNode = ConstructorParameters<typeof Provider>[0];
type MapDocumentNode = Exclude<ConstructorParameters<typeof Provider>[1], string>;
// This type is not exported from the sdk, but we want to pass it around for now TODO
type AuthConfig = Parameters<Provider['bind']>[0];

const readFile = promisify(fs.readFile);

async function loadAsts(
Expand All @@ -12,23 +18,23 @@ async function loadAsts(
providerName: string,
variantName?: string
): Promise<{
profile: ConstructorParameters<typeof Provider>[0],
map: Exclude<ConstructorParameters<typeof Provider>[1], string>
profile: ProfileDocumentNode,
map: MapDocumentNode
}> {
// if scope is not undefined, add it to the build path
// let buildPath = nodePath.join('superface', 'build');
let buildPath = nodePath.join('build');
// let buildPath = joinPath('superface', 'build');
let buildPath = joinPath('build');
if (scope !== undefined) {
buildPath = nodePath.join(buildPath, scope);
buildPath = joinPath(buildPath, scope);
}

// Read the profile and map ASTs from the build folder
const profileAst = JSON.parse(
await readFile(nodePath.join(buildPath, `${name}.supr.ast.json`), { encoding: 'utf-8' })
await readFile(joinPath(buildPath, `${name}.supr.ast.json`), { encoding: 'utf-8' })
);
const variant = variantName ? '.' + variantName : '';
const mapAst = JSON.parse(
await readFile(nodePath.join(buildPath, `${name}.${providerName}${variant}.suma.ast.json`), { encoding: 'utf-8' })
await readFile(joinPath(buildPath, `${name}.${providerName}${variant}.suma.ast.json`), { encoding: 'utf-8' })
);

// As this is a development script, the correct structure of the loaded asts is not checked
Expand All @@ -46,9 +52,9 @@ async function execute(
providerName: string,
variantName?: string,
baseUrl?: string,
auth?: Parameters<Provider['bind']>[0]
auth?: AuthConfig
) {
const asts = await loadAsts(scope, name, providerName, variantName);
const asts = await loadAsts(scope, name, providerName, variantName);

// 1. Create the provider object with the read ASTs
const provider = new Provider(
Expand Down Expand Up @@ -84,13 +90,13 @@ async function execute(

async function main() {
// Iterate over the input arguments
// Their expected format is `scope/name.provider.variant` (scope nad variant are optional)
// Their expected format is `scope/name.provider.variant` (scope and variant are optional)
for (const arg of process.argv.slice(2)) {
let scope: string | undefined = undefined;
let name: string = arg;
let provider: string = name;
let variant: string | undefined = undefined;

const scopeSplit = name.split('/');
if (scopeSplit.length === 2) {
scope = scopeSplit[0];
Expand Down Expand Up @@ -128,4 +134,4 @@ async function main() {
}
}

main();
main();
105 changes: 50 additions & 55 deletions src/commands/play.test.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
import * as nodePath from 'path';
import { join as joinPath } from 'path';
import { stdout } from 'stdout-stderr';

import Play from '../commands/play';
import { access, mkdir, OutputStream, rimraf } from '../common/io';

describe('Play CLI command', () => {
const baseFixture = nodePath.join('fixtures', 'playgrounds');
const testPlaygroundName = 'test';
const testPlaygroundPath = nodePath.join(baseFixture, testPlaygroundName);
const baseFixture = joinPath('fixtures', 'playgrounds');
const testPlaygroundName = 'create_test';
const testPlaygroundPath = joinPath(baseFixture, testPlaygroundName);

afterEach(async () => {
await rimraf(testPlaygroundPath);

const testFiles = [
'package-lock.json',
'node_modules',
nodePath.join('build', 'valid.supr.ast.json'),
nodePath.join('build', 'valid.noop.suma.ast.json'),
nodePath.join('build', 'valid.noop.js'),
joinPath('build', 'pub-hours.supr.ast.json'),
joinPath('build', 'pub-hours.noop.suma.ast.json'),
joinPath('build', 'pub-hours.play.js'),
];
await Promise.all(
testFiles.map(file => rimraf(nodePath.join(baseFixture, 'valid', file)))
testFiles.map(file => rimraf(joinPath(baseFixture, 'pub-hours', file)))
);
});

it('detects a valid playground', async () => {
await expect(
Play.run(['clean', nodePath.join(baseFixture, 'valid')])
Play.run(['clean', joinPath(baseFixture, 'pub-hours')])
).resolves.toBeUndefined();
});

it('rejects an an invalid playground', async () => {
await expect(
Play.run(['clean', nodePath.join(baseFixture, 'invalid')])
Play.run(['clean', joinPath(baseFixture, 'invalid')])
).rejects.toThrow('The directory at playground path is not a playground');
});

Expand All @@ -46,29 +46,27 @@ describe('Play CLI command', () => {
await expect(access(testPlaygroundPath)).resolves.toBeUndefined();
const expectedFiles = [
'package.json',
'test.supr',
'test.foo.suma',
'test.bar.suma',
'test.foo.ts',
'test.bar.ts',
`${testPlaygroundName}.supr`,
`${testPlaygroundName}.foo.suma`,
`${testPlaygroundName}.bar.suma`,
`${testPlaygroundName}.play.ts`,
'.gitignore',
];
for (const file of expectedFiles) {
await expect(
access(nodePath.join(testPlaygroundPath, file))
access(joinPath(testPlaygroundPath, file))
).resolves.toBeUndefined();
}

expect(stdout.output).toBe(
`$ mkdir fixtures/playgrounds/test
$ echo '<package template>' > fixtures/playgrounds/test/package.json
$ echo '<glue template>' > fixtures/playgrounds/test/test.foo.ts
$ echo '<glue template>' > fixtures/playgrounds/test/test.bar.ts
$ echo '<profile template>' > fixtures/playgrounds/test/test.supr
$ echo '<map template>' > fixtures/playgrounds/test/test.foo.suma
$ echo '<map template>' > fixtures/playgrounds/test/test.bar.suma
$ echo '<npmrc template>' > fixtures/playgrounds/test/.npmrc
$ echo '<gitignore template>' > fixtures/playgrounds/test/.gitignore
`$ mkdir fixtures/playgrounds/${testPlaygroundName}
$ echo '<package template>' > fixtures/playgrounds/${testPlaygroundName}/package.json
$ echo '<script template>' > fixtures/playgrounds/${testPlaygroundName}/${testPlaygroundName}.play.ts
$ echo '<profile template>' > fixtures/playgrounds/${testPlaygroundName}/${testPlaygroundName}.supr
$ echo '<map template>' > fixtures/playgrounds/${testPlaygroundName}/${testPlaygroundName}.foo.suma
$ echo '<map template>' > fixtures/playgrounds/${testPlaygroundName}/${testPlaygroundName}.bar.suma
$ echo '<npmrc template>' > fixtures/playgrounds/${testPlaygroundName}/.npmrc
$ echo '<gitignore template>' > fixtures/playgrounds/${testPlaygroundName}/.gitignore
`
);
});
Expand All @@ -93,25 +91,27 @@ $ echo '<gitignore template>' > fixtures/playgrounds/test/.gitignore
stdout.start();
await Play.run([
'execute',
nodePath.join(baseFixture, 'valid'),
joinPath(baseFixture, 'pub-hours'),
'--providers',
'noop',
]);
stdout.stop();

expect(stdout.output).toMatch(/pubs\/Noop result: Ok { value: \[\] }\s*$/);
expect(stdout.output).toMatch(
/PubOpeningHours\/noop result: Ok { value: \[\] }\s*$/
);

const expectedFiles = [
'package-lock.json',
'node_modules',
nodePath.join('build', 'valid.supr.ast.json'),
nodePath.join('build', 'valid.noop.suma.ast.json'),
nodePath.join('build', 'valid.noop.js'),
joinPath('build', 'pub-hours.supr.ast.json'),
joinPath('build', 'pub-hours.noop.suma.ast.json'),
joinPath('build', 'pub-hours.play.js'),
];
await expect(
Promise.all(
expectedFiles.map(file =>
access(nodePath.join(baseFixture, 'valid', file))
access(joinPath(baseFixture, 'pub-hours', file))
)
)
).resolves.toBeDefined();
Expand All @@ -121,29 +121,27 @@ $ echo '<gitignore template>' > fixtures/playgrounds/test/.gitignore
const deletedFiles = [
'package-lock.json',
'node_modules',
nodePath.join('build', 'test.supr.ast.json'),
nodePath.join('build', 'test.foo.suma.ast.json'),
nodePath.join('build', 'test.bar.suma.ast.json'),
nodePath.join('build', 'test.foo.js'),
nodePath.join('build', 'test.bar.js'),
joinPath('build', `${testPlaygroundName}.supr.ast.json`),
joinPath('build', `${testPlaygroundName}.foo.suma.ast.json`),
joinPath('build', `${testPlaygroundName}.bar.suma.ast.json`),
joinPath('build', `${testPlaygroundName}.play.js`),
];
const expectedFiles = [
'package.json',
'test.supr',
'test.foo.suma',
'test.bar.suma',
'test.foo.ts',
'test.bar.ts',
'test.baz.ts',
`${testPlaygroundName}.supr`,
`${testPlaygroundName}.foo.suma`,
`${testPlaygroundName}.bar.suma`,
`${testPlaygroundName}.play.ts`,
'.gitignore',
];

await mkdir(nodePath.join(testPlaygroundPath, 'build'), {
await mkdir(joinPath(testPlaygroundPath, 'build'), {
recursive: true,
});

await Promise.all(
[...deletedFiles, ...expectedFiles].map(file =>
OutputStream.writeOnce(nodePath.join(testPlaygroundPath, file), '')
OutputStream.writeOnce(joinPath(testPlaygroundPath, file), '')
)
);

Expand All @@ -155,27 +153,24 @@ $ echo '<gitignore template>' > fixtures/playgrounds/test/.gitignore

await Promise.all(
deletedFiles.map(file =>
expect(
access(nodePath.join(testPlaygroundPath, file))
).rejects.toThrowError('ENOENT')
expect(access(joinPath(testPlaygroundPath, file))).rejects.toThrowError(
'ENOENT'
)
)
);

await expect(
Promise.all(
expectedFiles.map(file =>
access(nodePath.join(testPlaygroundPath, file))
)
expectedFiles.map(file => access(joinPath(testPlaygroundPath, file)))
)
).resolves.toBeDefined();

expect(stdout.output).toMatch(/^\$ rimraf /);
expect(stdout.output).toMatch(/build\/test\.supr\.ast\.json'/);
expect(stdout.output).toMatch(/node_modules'/);
expect(stdout.output).toMatch(/package-lock\.json'/);
expect(stdout.output).toMatch(/build\/test\.bar\.suma\.ast\.json'/);
expect(stdout.output).toMatch(/build\/test\.bar\.js'/);
expect(stdout.output).toMatch(/build\/test\.foo\.suma\.ast\.json'/);
expect(stdout.output).toMatch(/build\/test\.foo\.js'/);
expect(stdout.output).toMatch(/build\/create_test\.supr\.ast\.json'/);
expect(stdout.output).toMatch(/build\/create_test\.bar\.suma\.ast\.json'/);
expect(stdout.output).toMatch(/build\/create_test\.play\.js'/);
expect(stdout.output).toMatch(/build\/create_test\.foo\.suma\.ast\.json'/);
});
});
4 changes: 2 additions & 2 deletions src/commands/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ clean: the \`node_modules\` folder and compilation artifacts are cleaned.`;
if (playgroundPath === undefined) {
playgroundPath = await Play.promptExistingPlayground();
}
const playground = await detectPlayground(playgroundPath);
const playground = (await detectPlayground(playgroundPath))[0]; // TODO: Do something about multiple instances

if (providers === undefined || providers.length === 0) {
const response: { providers: string[] } = await inquirer.prompt({
Expand Down Expand Up @@ -260,7 +260,7 @@ clean: the \`node_modules\` folder and compilation artifacts are cleaned.`;
if (playgroundPath === undefined) {
playgroundPath = await Play.promptExistingPlayground();
}
const playground = await detectPlayground(playgroundPath);
const playground = (await detectPlayground(playgroundPath))[0]; // TODO: Do something about multiple instances

this.debug('Playground:', playground);
await cleanPlayground(playground, this.logCallback);
Expand Down
25 changes: 25 additions & 0 deletions src/common/log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export function formatShellLog(
initial: string | undefined,
quoted?: string[],
env?: Record<string, string>
): string {
let envString = '';
if (env !== undefined) {
envString =
Object.entries(env)
.map(([key, value]) => `${key}='${value}'`)
.join(' ') + ' ';
}

let quotedString = '';
if (quoted !== undefined && quoted.length !== 0) {
quotedString = quoted.map(q => `'${q}'`).join(' ');
}

let initialString = (initial ?? '').trim();
if (initialString !== '' && quotedString !== '') {
initialString = initialString + ' ';
}

return `$ ${envString}${initialString}${quotedString}`;
}
Loading

0 comments on commit d3b6880

Please sign in to comment.