chore: refactor and simplify testing (#39050)
This commit is contained in:
committed by
GitHub
parent
5934984064
commit
b4926052f4
@ -1,206 +0,0 @@
|
||||
// originally based off of https://github.com/gulpjs/vinyl
|
||||
import invariant from 'invariant';
|
||||
import { Observable } from 'rx';
|
||||
import castToObservable from '../../server/utils/cast-to-observable';
|
||||
|
||||
// createFileStream(
|
||||
// files: [...PolyVinyl]
|
||||
// ) => Observable[...Observable[...PolyVinyl]]
|
||||
export function createFileStream(files = []) {
|
||||
return Observable.of(Observable.from(files));
|
||||
}
|
||||
|
||||
// Observable::pipe(
|
||||
// project(
|
||||
// file: PolyVinyl
|
||||
// ) => PolyVinyl|Observable[PolyVinyl]|Promise[PolyVinyl]
|
||||
// ) => Observable[...Observable[...PolyVinyl]]
|
||||
export function pipe(project) {
|
||||
const source = this;
|
||||
return source.map(files =>
|
||||
files.flatMap(file => castToObservable(project(file)))
|
||||
);
|
||||
}
|
||||
|
||||
// interface PolyVinyl {
|
||||
// source: String,
|
||||
// contents: String,
|
||||
// name: String,
|
||||
// ext: String,
|
||||
// path: String,
|
||||
// key: String,
|
||||
// head: String,
|
||||
// tail: String,
|
||||
// history: [...String],
|
||||
// error: Null|Object|Error
|
||||
// }
|
||||
|
||||
// createPoly({
|
||||
// name: String,
|
||||
// ext: String,
|
||||
// contents: String,
|
||||
// history?: [...String],
|
||||
// }) => PolyVinyl, throws
|
||||
export function createPoly({ name, ext, contents, history, ...rest } = {}) {
|
||||
invariant(typeof name === 'string', 'name must be a string but got %s', name);
|
||||
|
||||
invariant(typeof ext === 'string', 'ext must be a string, but was %s', ext);
|
||||
|
||||
invariant(
|
||||
typeof contents === 'string',
|
||||
'contents must be a string but got %s',
|
||||
contents
|
||||
);
|
||||
|
||||
return {
|
||||
...rest,
|
||||
history: Array.isArray(history) ? history : [name + ext],
|
||||
name,
|
||||
ext,
|
||||
path: name + '.' + ext,
|
||||
key: name + ext,
|
||||
contents,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
|
||||
// isPoly(poly: Any) => Boolean
|
||||
export function isPoly(poly) {
|
||||
return (
|
||||
poly &&
|
||||
typeof poly.contents === 'string' &&
|
||||
typeof poly.name === 'string' &&
|
||||
typeof poly.ext === 'string' &&
|
||||
Array.isArray(poly.history)
|
||||
);
|
||||
}
|
||||
|
||||
// checkPoly(poly: Any) => Void, throws
|
||||
export function checkPoly(poly) {
|
||||
invariant(
|
||||
isPoly(poly),
|
||||
'function should receive a PolyVinyl, but got %s',
|
||||
poly
|
||||
);
|
||||
}
|
||||
|
||||
// isEmpty(poly: PolyVinyl) => Boolean, throws
|
||||
export function isEmpty(poly) {
|
||||
checkPoly(poly);
|
||||
return !!poly.contents;
|
||||
}
|
||||
|
||||
// setContent(contents: String, poly: PolyVinyl) => PolyVinyl
|
||||
// setContent will loose source if set
|
||||
export function setContent(contents, poly) {
|
||||
checkPoly(poly);
|
||||
return {
|
||||
...poly,
|
||||
contents,
|
||||
source: null
|
||||
};
|
||||
}
|
||||
|
||||
// setExt(ext: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function setExt(ext, poly) {
|
||||
checkPoly(poly);
|
||||
const newPoly = {
|
||||
...poly,
|
||||
ext,
|
||||
path: poly.name + '.' + ext,
|
||||
key: poly.name + ext
|
||||
};
|
||||
newPoly.history = [...poly.history, newPoly.path];
|
||||
return newPoly;
|
||||
}
|
||||
|
||||
// setName(name: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function setName(name, poly) {
|
||||
checkPoly(poly);
|
||||
const newPoly = {
|
||||
...poly,
|
||||
name,
|
||||
path: name + '.' + poly.ext,
|
||||
key: name + poly.ext
|
||||
};
|
||||
newPoly.history = [...poly.history, newPoly.path];
|
||||
return newPoly;
|
||||
}
|
||||
|
||||
// setError(error: Object, poly: PolyVinyl) => PolyVinyl
|
||||
export function setError(error, poly) {
|
||||
invariant(
|
||||
typeof error === 'object',
|
||||
'error must be an object or null, but got %',
|
||||
error
|
||||
);
|
||||
checkPoly(poly);
|
||||
return {
|
||||
...poly,
|
||||
error
|
||||
};
|
||||
}
|
||||
|
||||
// clearHeadTail(poly: PolyVinyl) => PolyVinyl
|
||||
export function clearHeadTail(poly) {
|
||||
checkPoly(poly);
|
||||
return {
|
||||
...poly,
|
||||
head: '',
|
||||
tail: ''
|
||||
};
|
||||
}
|
||||
|
||||
// appendToTail (tail: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function appendToTail(tail, poly) {
|
||||
checkPoly(poly);
|
||||
return {
|
||||
...poly,
|
||||
tail: poly.tail.concat(tail)
|
||||
};
|
||||
}
|
||||
|
||||
// compileHeadTail(padding: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function compileHeadTail(padding = '', poly) {
|
||||
return clearHeadTail(
|
||||
transformContents(
|
||||
() => [poly.head, poly.contents, poly.tail].join(padding),
|
||||
poly
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// transformContents(
|
||||
// wrap: (contents: String) => String,
|
||||
// poly: PolyVinyl
|
||||
// ) => PolyVinyl
|
||||
// transformContents will keep a copy of the original
|
||||
// code in the `source` property. If the original polyvinyl
|
||||
// already contains a source, this version will continue as
|
||||
// the source property
|
||||
export function transformContents(wrap, poly) {
|
||||
const newPoly = setContent(wrap(poly.contents), poly);
|
||||
// if no source exist, set the original contents as source
|
||||
newPoly.source = poly.source || poly.contents;
|
||||
return newPoly;
|
||||
}
|
||||
|
||||
// transformHeadTailAndContents(
|
||||
// wrap: (source: String) => String,
|
||||
// poly: PolyVinyl
|
||||
// ) => PolyVinyl
|
||||
export function transformHeadTailAndContents(wrap, poly) {
|
||||
return {
|
||||
...transformContents(wrap, poly),
|
||||
head: wrap(poly.head),
|
||||
tail: wrap(poly.tail)
|
||||
};
|
||||
}
|
||||
|
||||
export function testContents(predicate, poly) {
|
||||
return !!predicate(poly.contents);
|
||||
}
|
||||
|
||||
export function updateFileFromSpec(spec, poly) {
|
||||
return setContent(poly.contents, createPoly(spec));
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import validator from 'express-validator';
|
||||
import { isPoly } from '../../common/utils/polyvinyl';
|
||||
import { isPoly } from '../../../utils/polyvinyl';
|
||||
|
||||
const isObject = val => !!val && typeof val === 'object';
|
||||
|
||||
|
@ -3,7 +3,7 @@ const env = require('../config/env');
|
||||
const { createFilePath } = require('gatsby-source-filesystem');
|
||||
|
||||
const { dasherize } = require('../utils/slugs');
|
||||
const { blockNameify } = require('./utils/blockNameify');
|
||||
const { blockNameify } = require('../utils/block-nameify');
|
||||
const {
|
||||
createChallengePages,
|
||||
createBlockIntroPages,
|
||||
|
@ -6,7 +6,7 @@ import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { Modal, Button, Col, Row } from '@freecodecamp/react-bootstrap';
|
||||
import { Spacer } from '../helpers';
|
||||
import { blockNameify } from '../../../utils/blockNameify';
|
||||
import { blockNameify } from '../../../../utils/block-nameify';
|
||||
import Heart from '../../assets/icons/Heart';
|
||||
import Cup from '../../assets/icons/Cup';
|
||||
import MinimalDonateForm from './MinimalDonateForm';
|
||||
|
@ -8,7 +8,7 @@ import { Link } from 'gatsby';
|
||||
import { makeExpandedBlockSelector, toggleBlock } from '../redux';
|
||||
import { completedChallengesSelector, executeGA } from '../../../redux';
|
||||
import Caret from '../../../assets/icons/Caret';
|
||||
import { blockNameify } from '../../../../utils/blockNameify';
|
||||
import { blockNameify } from '../../../../../utils/block-nameify';
|
||||
import GreenPass from '../../../assets/icons/GreenPass';
|
||||
import GreenNotCompleted from '../../../assets/icons/GreenNotCompleted';
|
||||
import IntroInformation from '../../../assets/icons/IntroInformation';
|
||||
|
@ -8,7 +8,11 @@ import {
|
||||
template as _template
|
||||
} from 'lodash';
|
||||
|
||||
import { compileHeadTail, setExt, transformContents } from '../utils/polyvinyl';
|
||||
import {
|
||||
compileHeadTail,
|
||||
setExt,
|
||||
transformContents
|
||||
} from '../../../../../utils/polyvinyl';
|
||||
|
||||
const htmlCatch = '\n<!--fcc-->\n';
|
||||
const jsCatch = '\n;/*fcc*/\n';
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
|
||||
import protect from '@freecodecamp/loop-protect';
|
||||
|
||||
import * as vinyl from '../utils/polyvinyl.js';
|
||||
import * as vinyl from '../../../../../utils/polyvinyl.js';
|
||||
import createWorker from '../utils/worker-executor';
|
||||
|
||||
// the config files are created during the build, but not before linting
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
|
||||
import { types as appTypes } from '../../../redux';
|
||||
|
||||
import { setContent, isPoly } from '../utils/polyvinyl';
|
||||
import { setContent, isPoly } from '../../../../../utils/polyvinyl';
|
||||
|
||||
import { createFlashMessage } from '../../../components/Flash/redux';
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { createAction, handleActions } from 'redux-actions';
|
||||
|
||||
import { createTypes } from '../../../../utils/stateManagement';
|
||||
|
||||
import { createPoly } from '../utils/polyvinyl';
|
||||
import { createPoly } from '../../../../../utils/polyvinyl';
|
||||
import challengeModalEpic from './challenge-modal-epic';
|
||||
import completionEpic from './completion-epic';
|
||||
import codeLockEpic from './code-lock-epic';
|
||||
|
@ -7,7 +7,7 @@ const {
|
||||
} = require('../../curriculum/getChallenges');
|
||||
const { dasherize, nameify } = require('../../utils/slugs');
|
||||
const { locale } = require('../config/env.json');
|
||||
const { blockNameify } = require('./blockNameify');
|
||||
const { blockNameify } = require('../../utils/block-nameify');
|
||||
|
||||
const arrToString = arr =>
|
||||
Array.isArray(arr) ? arr.join('\n') : _.toString(arr);
|
||||
|
@ -6,8 +6,6 @@ const fs = require('fs');
|
||||
|
||||
const { dasherize } = require('../utils/slugs');
|
||||
|
||||
const { challengeSchemaValidator } = require('./schema/challengeSchema');
|
||||
|
||||
const challengesDir = path.resolve(__dirname, './challenges');
|
||||
const metaDir = path.resolve(challengesDir, '_meta');
|
||||
exports.challengesDir = challengesDir;
|
||||
@ -38,13 +36,13 @@ exports.getChallengesForLang = function getChallengesForLang(lang) {
|
||||
readDirP({ root: getChallengesDirForLang(lang) })
|
||||
.on('data', file => {
|
||||
running++;
|
||||
buildCurriculum(file, curriculum, lang).then(done);
|
||||
buildCurriculum(file, curriculum).then(done);
|
||||
})
|
||||
.on('end', done);
|
||||
});
|
||||
};
|
||||
|
||||
async function buildCurriculum(file, curriculum, lang) {
|
||||
async function buildCurriculum(file, curriculum) {
|
||||
const { name, depth, path: filePath, fullPath, stat } = file;
|
||||
if (depth === 1 && stat.isDirectory()) {
|
||||
// extract the superBlock info
|
||||
@ -80,12 +78,12 @@ async function buildCurriculum(file, curriculum, lang) {
|
||||
}
|
||||
const { meta } = challengeBlock;
|
||||
|
||||
const challenge = await createChallenge(fullPath, meta, lang);
|
||||
const challenge = await createChallenge(fullPath, meta);
|
||||
|
||||
challengeBlock.challenges = [...challengeBlock.challenges, challenge];
|
||||
}
|
||||
|
||||
async function createChallenge(fullPath, maybeMeta, lang) {
|
||||
async function createChallenge(fullPath, maybeMeta) {
|
||||
let meta;
|
||||
if (maybeMeta) {
|
||||
meta = maybeMeta;
|
||||
@ -98,11 +96,6 @@ async function createChallenge(fullPath, maybeMeta, lang) {
|
||||
}
|
||||
const { name: superBlock } = superBlockInfoFromFullPath(fullPath);
|
||||
const challenge = await parseMarkdown(fullPath);
|
||||
const result = challengeSchemaValidator(lang)(challenge);
|
||||
if (result.error) {
|
||||
console.log(result.value);
|
||||
throw new Error(result.error);
|
||||
}
|
||||
const challengeOrder = findIndex(
|
||||
meta.challengeOrder,
|
||||
([id]) => id === challenge.id
|
||||
|
@ -53,9 +53,7 @@ const {
|
||||
buildJSChallenge
|
||||
} = require('../../client/src/templates/Challenges/utils/build');
|
||||
|
||||
const {
|
||||
createPoly
|
||||
} = require('../../client/src/templates/Challenges/utils/polyvinyl');
|
||||
const { createPoly } = require('../../utils/polyvinyl');
|
||||
|
||||
const testEvaluator = require('../../client/config/test-evaluator').filename;
|
||||
|
||||
@ -323,24 +321,24 @@ function populateTestsForLang({ lang, challenges }, meta) {
|
||||
});
|
||||
|
||||
let { files = [] } = challenge;
|
||||
let createTestRunner;
|
||||
if (challengeType === challengeTypes.backend) {
|
||||
it('Check tests is not implemented.');
|
||||
return;
|
||||
} else if (
|
||||
challengeType === challengeTypes.js ||
|
||||
challengeType === challengeTypes.bonfire
|
||||
) {
|
||||
createTestRunner = createTestRunnerForJSChallenge;
|
||||
} else if (files.length === 1) {
|
||||
createTestRunner = createTestRunnerForDOMChallenge;
|
||||
} else {
|
||||
}
|
||||
|
||||
if (files.length > 1) {
|
||||
it('Check tests.', () => {
|
||||
throw new Error('Seed file should be only the one.');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const buildChallenge =
|
||||
challengeType === challengeTypes.js ||
|
||||
challengeType === challengeTypes.bonfire
|
||||
? buildJSChallenge
|
||||
: buildDOMChallenge;
|
||||
|
||||
files = files.map(createPoly);
|
||||
it('Test suite must fail on the initial contents', async function() {
|
||||
this.timeout(5000 * tests.length + 1000);
|
||||
@ -353,7 +351,7 @@ function populateTestsForLang({ lang, challenges }, meta) {
|
||||
testRunner = await createTestRunner(
|
||||
{ ...challenge, files },
|
||||
'',
|
||||
page
|
||||
buildChallenge
|
||||
);
|
||||
} catch {
|
||||
fails = true;
|
||||
@ -390,7 +388,7 @@ function populateTestsForLang({ lang, challenges }, meta) {
|
||||
const testRunner = await createTestRunner(
|
||||
{ ...challenge, files },
|
||||
solution,
|
||||
page
|
||||
buildChallenge
|
||||
);
|
||||
for (const test of tests) {
|
||||
await testRunner(test);
|
||||
@ -404,41 +402,29 @@ function populateTestsForLang({ lang, challenges }, meta) {
|
||||
});
|
||||
}
|
||||
|
||||
async function createTestRunnerForDOMChallenge(
|
||||
async function createTestRunner(
|
||||
{ required = [], template, files },
|
||||
solution,
|
||||
context
|
||||
buildChallenge
|
||||
) {
|
||||
if (solution) {
|
||||
files[0].contents = solution;
|
||||
}
|
||||
|
||||
const { build, sources, loadEnzyme } = await buildDOMChallenge({
|
||||
const { build, sources, loadEnzyme } = await buildChallenge({
|
||||
files,
|
||||
required,
|
||||
template
|
||||
});
|
||||
|
||||
await context.reload();
|
||||
await context.setContent(build);
|
||||
await context.evaluate(
|
||||
async (sources, loadEnzyme) => {
|
||||
const code = sources && 'index' in sources ? sources['index'] : '';
|
||||
const getUserInput = fileName => sources[fileName];
|
||||
await document.__initTestFrame({ code, getUserInput, loadEnzyme });
|
||||
},
|
||||
sources,
|
||||
loadEnzyme
|
||||
);
|
||||
|
||||
const evaluator = await (buildChallenge === buildDOMChallenge
|
||||
? getContextEvaluator(build, sources, code, loadEnzyme)
|
||||
: getWorkerEvaluator(build, sources, code));
|
||||
|
||||
return async ({ text, testString }) => {
|
||||
try {
|
||||
const { pass, err } = await Promise.race([
|
||||
new Promise((_, reject) => setTimeout(() => reject('timeout'), 5000)),
|
||||
await context.evaluate(async testString => {
|
||||
return await document.__runTest(testString);
|
||||
}, testString)
|
||||
]);
|
||||
const { pass, err } = await evaluator.evaluate(testString, 5000);
|
||||
if (!pass) {
|
||||
throw new AssertionError(err.message);
|
||||
}
|
||||
@ -448,30 +434,45 @@ async function createTestRunnerForDOMChallenge(
|
||||
};
|
||||
}
|
||||
|
||||
async function createTestRunnerForJSChallenge({ files }, solution) {
|
||||
if (solution) {
|
||||
files[0].contents = solution;
|
||||
}
|
||||
async function getContextEvaluator(build, sources, code, loadEnzyme) {
|
||||
await initializeTestRunner(build, sources, code, loadEnzyme);
|
||||
|
||||
const { build, sources } = await buildJSChallenge({ files });
|
||||
const code = sources && 'index' in sources ? sources['index'] : '';
|
||||
|
||||
const testWorker = createWorker(testEvaluator, { terminateWorker: true });
|
||||
return async ({ text, testString }) => {
|
||||
try {
|
||||
const { pass, err } = await testWorker.execute(
|
||||
{ testString, build, code, sources },
|
||||
5000
|
||||
).done;
|
||||
if (!pass) {
|
||||
throw new AssertionError(err.message);
|
||||
}
|
||||
} catch (err) {
|
||||
reThrow(err, text);
|
||||
}
|
||||
return {
|
||||
evaluate: async (testString, timeout) =>
|
||||
Promise.race([
|
||||
new Promise((_, reject) =>
|
||||
setTimeout(() => reject('timeout'), timeout)
|
||||
),
|
||||
await page.evaluate(async testString => {
|
||||
return await document.__runTest(testString);
|
||||
}, testString)
|
||||
])
|
||||
};
|
||||
}
|
||||
|
||||
async function getWorkerEvaluator(build, sources, code) {
|
||||
const testWorker = createWorker(testEvaluator, { terminateWorker: true });
|
||||
return {
|
||||
evaluate: async (testString, timeout) =>
|
||||
await testWorker.execute({ testString, build, code, sources }, timeout)
|
||||
.done
|
||||
};
|
||||
}
|
||||
|
||||
async function initializeTestRunner(build, sources, code, loadEnzyme) {
|
||||
await page.reload();
|
||||
await page.setContent(build);
|
||||
await page.evaluate(
|
||||
async (code, sources, loadEnzyme) => {
|
||||
const getUserInput = fileName => sources[fileName];
|
||||
await document.__initTestFrame({ code, getUserInput, loadEnzyme });
|
||||
},
|
||||
code,
|
||||
sources,
|
||||
loadEnzyme
|
||||
);
|
||||
}
|
||||
|
||||
function reThrow(err, text) {
|
||||
if (typeof err === 'string') {
|
||||
throw new AssertionError(
|
||||
|
@ -1,14 +1,17 @@
|
||||
// originally based off of https://github.com/gulpjs/vinyl
|
||||
import invariant from 'invariant';
|
||||
import { of, from, isObservable } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
const invariant = require('invariant');
|
||||
const { of, from, isObservable } = require('rxjs');
|
||||
const { map, switchMap } = require('rxjs/operators');
|
||||
|
||||
export const isPromise = value =>
|
||||
function isPromise(value) {
|
||||
return (
|
||||
value &&
|
||||
typeof value.subscribe !== 'function' &&
|
||||
typeof value.then === 'function';
|
||||
typeof value.then === 'function'
|
||||
);
|
||||
}
|
||||
|
||||
export function castToObservable(maybe) {
|
||||
function castToObservable(maybe) {
|
||||
if (isObservable(maybe)) {
|
||||
return maybe;
|
||||
}
|
||||
@ -21,7 +24,7 @@ export function castToObservable(maybe) {
|
||||
// createFileStream(
|
||||
// files: [...PolyVinyl]
|
||||
// ) => Observable[...Observable[...PolyVinyl]]
|
||||
export function createFileStream(files = []) {
|
||||
function createFileStream(files = []) {
|
||||
return of(from(files));
|
||||
}
|
||||
|
||||
@ -30,7 +33,7 @@ export function createFileStream(files = []) {
|
||||
// file: PolyVinyl
|
||||
// ) => PolyVinyl|Observable[PolyVinyl]|Promise[PolyVinyl]
|
||||
// ) => Observable[...Observable[...PolyVinyl]]
|
||||
export function pipe(project) {
|
||||
function pipe(project) {
|
||||
const source = this;
|
||||
return source.pipe(
|
||||
map(files => {
|
||||
@ -58,7 +61,7 @@ export function pipe(project) {
|
||||
// contents: String,
|
||||
// history?: [...String],
|
||||
// }) => PolyVinyl, throws
|
||||
export function createPoly({ name, ext, contents, history, ...rest } = {}) {
|
||||
function createPoly({ name, ext, contents, history, ...rest } = {}) {
|
||||
invariant(typeof name === 'string', 'name must be a string but got %s', name);
|
||||
|
||||
invariant(typeof ext === 'string', 'ext must be a string, but was %s', ext);
|
||||
@ -82,7 +85,7 @@ export function createPoly({ name, ext, contents, history, ...rest } = {}) {
|
||||
}
|
||||
|
||||
// isPoly(poly: Any) => Boolean
|
||||
export function isPoly(poly) {
|
||||
function isPoly(poly) {
|
||||
return (
|
||||
poly &&
|
||||
typeof poly.contents === 'string' &&
|
||||
@ -93,7 +96,7 @@ export function isPoly(poly) {
|
||||
}
|
||||
|
||||
// checkPoly(poly: Any) => Void, throws
|
||||
export function checkPoly(poly) {
|
||||
function checkPoly(poly) {
|
||||
invariant(
|
||||
isPoly(poly),
|
||||
'function should receive a PolyVinyl, but got %s',
|
||||
@ -102,14 +105,14 @@ export function checkPoly(poly) {
|
||||
}
|
||||
|
||||
// isEmpty(poly: PolyVinyl) => Boolean, throws
|
||||
export function isEmpty(poly) {
|
||||
function isEmpty(poly) {
|
||||
checkPoly(poly);
|
||||
return !!poly.contents;
|
||||
}
|
||||
|
||||
// setContent(contents: String, poly: PolyVinyl) => PolyVinyl
|
||||
// setContent will loose source if set
|
||||
export function setContent(contents, poly) {
|
||||
function setContent(contents, poly) {
|
||||
checkPoly(poly);
|
||||
return {
|
||||
...poly,
|
||||
@ -119,7 +122,7 @@ export function setContent(contents, poly) {
|
||||
}
|
||||
|
||||
// setExt(ext: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function setExt(ext, poly) {
|
||||
function setExt(ext, poly) {
|
||||
checkPoly(poly);
|
||||
const newPoly = {
|
||||
...poly,
|
||||
@ -132,7 +135,7 @@ export function setExt(ext, poly) {
|
||||
}
|
||||
|
||||
// setName(name: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function setName(name, poly) {
|
||||
function setName(name, poly) {
|
||||
checkPoly(poly);
|
||||
const newPoly = {
|
||||
...poly,
|
||||
@ -145,7 +148,7 @@ export function setName(name, poly) {
|
||||
}
|
||||
|
||||
// setError(error: Object, poly: PolyVinyl) => PolyVinyl
|
||||
export function setError(error, poly) {
|
||||
function setError(error, poly) {
|
||||
invariant(
|
||||
typeof error === 'object',
|
||||
'error must be an object or null, but got %',
|
||||
@ -159,7 +162,7 @@ export function setError(error, poly) {
|
||||
}
|
||||
|
||||
// clearHeadTail(poly: PolyVinyl) => PolyVinyl
|
||||
export function clearHeadTail(poly) {
|
||||
function clearHeadTail(poly) {
|
||||
checkPoly(poly);
|
||||
return {
|
||||
...poly,
|
||||
@ -169,7 +172,7 @@ export function clearHeadTail(poly) {
|
||||
}
|
||||
|
||||
// appendToTail (tail: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function appendToTail(tail, poly) {
|
||||
function appendToTail(tail, poly) {
|
||||
checkPoly(poly);
|
||||
return {
|
||||
...poly,
|
||||
@ -178,7 +181,7 @@ export function appendToTail(tail, poly) {
|
||||
}
|
||||
|
||||
// compileHeadTail(padding: String, poly: PolyVinyl) => PolyVinyl
|
||||
export function compileHeadTail(padding = '', poly) {
|
||||
function compileHeadTail(padding = '', poly) {
|
||||
return clearHeadTail(
|
||||
transformContents(
|
||||
() => [poly.head, poly.contents, poly.tail].join(padding),
|
||||
@ -195,7 +198,7 @@ export function compileHeadTail(padding = '', poly) {
|
||||
// code in the `source` property. If the original polyvinyl
|
||||
// already contains a source, this version will continue as
|
||||
// the source property
|
||||
export function transformContents(wrap, poly) {
|
||||
function transformContents(wrap, poly) {
|
||||
const newPoly = setContent(wrap(poly.contents), poly);
|
||||
// if no source exist, set the original contents as source
|
||||
newPoly.source = poly.source || poly.contents;
|
||||
@ -206,7 +209,7 @@ export function transformContents(wrap, poly) {
|
||||
// wrap: (source: String) => String,
|
||||
// poly: PolyVinyl
|
||||
// ) => PolyVinyl
|
||||
export function transformHeadTailAndContents(wrap, poly) {
|
||||
function transformHeadTailAndContents(wrap, poly) {
|
||||
return {
|
||||
...transformContents(wrap, poly),
|
||||
head: wrap(poly.head),
|
||||
@ -214,10 +217,32 @@ export function transformHeadTailAndContents(wrap, poly) {
|
||||
};
|
||||
}
|
||||
|
||||
export function testContents(predicate, poly) {
|
||||
function testContents(predicate, poly) {
|
||||
return !!predicate(poly.contents);
|
||||
}
|
||||
|
||||
export function updateFileFromSpec(spec, poly) {
|
||||
function updateFileFromSpec(spec, poly) {
|
||||
return setContent(poly.contents, createPoly(spec));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isPromise,
|
||||
castToObservable,
|
||||
createFileStream,
|
||||
pipe,
|
||||
createPoly,
|
||||
isPoly,
|
||||
checkPoly,
|
||||
isEmpty,
|
||||
setContent,
|
||||
setExt,
|
||||
setName,
|
||||
setError,
|
||||
clearHeadTail,
|
||||
appendToTail,
|
||||
compileHeadTail,
|
||||
transformContents,
|
||||
transformHeadTailAndContents,
|
||||
testContents,
|
||||
updateFileFromSpec
|
||||
};
|
Reference in New Issue
Block a user