Files
freeCodeCamp/common/utils/polyvinyl.js
Berkeley Martinez b2b1426e22 Feat: react redux migration (#16200)
* feat: crudely enables test to run solution code against React challenge (and passes!)

* feat: Updates comment

* feat: Adds React 2 and 3, validates challenges in app

* feat: Adds React 4, validates tests

* feat: Adds Peter's migrated challenge seed files for all challenges

* feat: Adds redux, react-redux imports, adds tests for React 7,

* feat: Adds tests for React 08

* fix(challenges): wrap reserved words in <code> and add tests

* feat: complete first two tests for React 9

* feat: modifies tests in React 09

* feat: Adds working tests for React 37, including async setState tests

* feat: Escape hatch to avoid async tests in automated test suite

* feat: Updates React 15 with working tests

* feat: build passes, yay

* feat: Provisions original code string in challenges and adds tests for React Redux 01

* fix(tests): add self-closing tags challenge, other small fixes

* fix(challenge): add react_10, some other stuff

* fix(challenges): update react 22, add react 23

* fix(challenges): react 5 and react 8

* feat: removes dependencies that will break in browser, will replace later

* feat: fix build

* feat: add redux 1

* fix(challenge): add react 24 tests

* feat: partial implemented Redux 2

* feat: migrate redux 3

* feat: Adds React-Redux 04 with working tests under npm test

* feat: Updates automated test runner, just provide all the dependencies. Adds Redux-Thunk.

* feat: Adds working tests for React Redux 07

* feat: redux challenge 4

* feat: migrate redux 5

* feat: redux 6

* feat: migrate Redux test 7

* fix(challenge): add react 25 tests

* feat: Adds tests for React 48, npm test does not pass...

* feat: Migrate Redux test 8

* fix(challenges): skip 26, add react 27 tests

* fix(challenges): add react 28 tests, replace function w/ => throughout, fix linter warnings

* feat: fixes (patches) hard to understand problem with automated test suite

* feat: updates async tests patch

* feat: adds converted tests for React 47

* feat: adds converted tests for React 46

* feat: Partially adds tests for React 43

* docs: adds TO-DO tests for React 43

* feat: migrates tests for React 42

* feat: migrates tests for React 41

* feat: migrates tests for React 39

* feat: Migrates tests for React 38, automated test script fails again!

* feat: migrates tests for React 32

* feat: QAs more React Redux challenge in FCC UI

* feat: Updates tests for React 7

* feat: Migrates React-Redux 3 tests and hardcodes deep-freeze dependency

* feat: migrates React Redux 05 tests

* feat: migrates React Redux 06 tests

* feat: Migrates React Redux 10

* feat: Migrates tests for React 16

* feat: Migrates React 17 tests

* feat: Migrates React 18 tests

* feat: Migrates React 19 tests

* feat: Migrates React 19 tests

* feat: fixing usage of code, replace with editor.getOriginalCode

* feat: Migrates React 21 tests

* feat: Finishes migration of React 09

* fix(challenges): add react 45 tests 💀

* feat: Adds React 11 tests

* feat: Migrates React 50 tests

* feat: Re-enables original code in FCC editor, QAs challenges blocked by original code

* feat: hacks head tail code in editor test environment

* feat: updates React 20 head code

* feat: QAs React Redux 07 in UI

* fix(challenges): add React 29 tests

* fix(challenges): add React 30 tests

* feat: updates async tests

* feat: Migrates React 12, gets ReactDOM challenges working and QAs them

* feat: Migrates React 13 tests

* feat: Migrates tests for React 14 and updates challenge description formatting

* feat: Refactors 2nd test for Redux 02

* feat: Migrates React 33

* feat: Removes React 26 and 43

* feat: Adds React 34 from Kevin

* fix(challenges): add React 31 & 35 tests (thanks Kevin)

* feat: Migrate Redux challenge 10 - pass both UI QA and terminal test

* fix(challenge): add react 40 tests

* feat: Migrates React Redux 02 tests

* feat: Migrates React Redux 08 and fixes async syntax in React challenge

* fix(challenge): add react 49 tests with caveat

* feat: fixes React 49 tests and adds first tests for React Redux 09

* feat: Migrate Redux 11 - pass both terminal test and UI test

* feat: Migrate Redux 12 - passing both UI test and terminal test

* feat: Migrate Redux 13 - passing both terminal and UI tests

* feat: Adding in code tags for previous redux challenges - terminal and UI tests pass

* feat: Migrates React Redux 09 and React 44 (thanks Kevin)

* feat: fix code tag issues - passed UI and terminal tests

* feat: Migrates Redux 14 tests

* feat: Migrates Redux 14

* feat: Migrates Redux 15

* feat: Migrates Redux 17

* feat: Final migration and QA of Redux, except for Redux 9

* feat: migrates React 36 and QAs

* feat: Rewrites Redux 09 and migrates

* feat: refactors pull request and cleans up code

* style(challenges): QA React challenges

* style(challenges): QA react challenges

* fix(challenges): fix react 41 and 45 tests

* style(challenges): QA redux challenges

* style(challenges): QA react and redux challenges

* fix(seed/react): Move head/tail to files

* fix(seed/redux): Move head/tail to file level

* chore(packages): Move jsdom to dev deps

* fix(seed/react/redux): Async funcs

make async func defined

* fix(seed): %s/editor.getUserCode/getUserInput/gc

* fix(Challenges/build): Make sure head/tail is bundled and transformed

* feat(Challenges.react): Add tail to render component

* chore(seed): Disable modern challenge testing for now

We will put these on beta while we update the auto testing framework
2017-12-18 15:04:03 -06:00

217 lines
4.7 KiB
JavaScript

// originally based off of https://github.com/gulpjs/vinyl
import invariant from 'invariant';
import { Observable } from 'rx';
import castToObservable from '../app/utils/cast-to-observable.js';
// createFileStream(
// files: Dictionary[Path, PolyVinyl]
// ) => Observable[...Observable[...PolyVinyl]]
export function createFileStream(files = {}) {
return Observable.of(
Observable.from(Object.keys(files).map(key => files[key]))
);
}
// 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(contents: 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(contents: 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(contents: String, 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: ''
};
}
// compileHeadTail(contents: 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));
}