diff --git a/bin/run.sh b/bin/run.sh index 2e0b9a2..f41c0c1 100755 --- a/bin/run.sh +++ b/bin/run.sh @@ -81,25 +81,37 @@ REPORTER="$ROOT/dist/reporter.js" SETUP="$ROOT/dist/jest/setup.js" CONFIG="$ROOT/jest.runner.config.js" -if test -f "$REPORTER"; then - echo "Using reporter : $REPORTER" - echo "Using test-root: $INPUT" - echo "Using base-root: $ROOT" - echo "Using setup-env: $SETUP" +echo "" +echo "╔═════════════════════════════════════════════════════════════╗" +echo " 🔧 Process input arguments for run " +echo "╚═════════════════════════════════════════════════════════════╝" +echo "" - echo "" + +if test -f "$REPORTER"; then + echo "✔️ Using reporter : $REPORTER" + echo "✔️ Using test-root: $INPUT" + echo "✔️ Using base-root: $ROOT" + echo "✔️ Using setup-env: $SETUP" else - >&2 echo "Expected reporter.js to exist. Did you forget to 'corepack yarn build' first?" - >&2 echo "Using reporter : $REPORTER" - >&2 echo "Using test-root: $INPUT" - >&2 echo "Using base-root: $ROOT" - >&2 echo "Using setup-env: $SETUP" + echo "✔️ Using reporter : $REPORTER" + echo "✔️ Using test-root: $INPUT" + echo "✔️ Using base-root: $ROOT" + echo "✔️ Using setup-env: $SETUP" + + >&2 echo "❌ Expected reporter.js to exist." + >&2 echo "❌ Did you forget to 'corepack yarn build' first?" >&2 echo "" - >&2 echo "The following files exist in the dist folder (build output):" + >&2 echo "👁️ The following files exist in the dist folder (build output):" >&2 echo $(ls $ROOT/dist) + exit 1 fi +echo "" +echo "╔═════════════════════════════════════════════════════════════╗" +echo " 🔧 Preparing run " +echo "╚═════════════════════════════════════════════════════════════╝" echo "" configuration_file="${INPUT}.meta/config.json" @@ -109,91 +121,167 @@ local_configuration_file="${INPUT}.exercism/config.json" mkdir -p "${OUTPUT}" if [[ "${INPUT}" -ef "${OUTPUT}" ]]; then - echo "${INPUT} matches ${OUTPUT}. Not copying input to output." + echo "Input matches output directory." + echo "👁️ ${OUTPUT}" + echo "✔️ Not copying input to output." + echo "" else - echo "Copying ${INPUT} to ${OUTPUT}." + echo "Input does not match output directory." + echo "👁️ ${OUTPUT}" + echo "✔️ Copying ${INPUT} to output." cp -r "${INPUT}/." "${OUTPUT}" - cp -r "${ROOT}/.yarn" "${OUTPUT}" - cp "${ROOT}/.yarnrc.yml" "${OUTPUT}/.yarnrc.yml" - cp "${ROOT}/yarn.lock" "${OUTPUT}/yarn.lock" - cp "${ROOT}/.pnp.cjs" "${OUTPUT}/.pnp.cjs" - cp "${ROOT}/.pnp.loader.mjs" "${OUTPUT}/.pnp.loader.mjs" - - # Rename babel.config.js and package.json - if test -f "${OUTPUT}babel.config.js"; then - mv "${OUTPUT}babel.config.js" "${OUTPUT}babel.config.js.__exercism.bak" || true - fi; - - if test -f "${OUTPUT}package.json"; then - mv "${OUTPUT}package.json" "${OUTPUT}package.json.__exercism.bak" || true - fi; + echo "" fi -# Rename babel.config.js and package.json -echo "Disabling babel.config.js and package.json from input, if any" +echo "If the solution contains babel.config.js, package.json, " +echo "or tsconfig.json at the root, these configuration files will " +echo "be used during the test-runner process which we do not want. " +echo "The test-runner will therefore temporarily rename these files." +echo "" + +# Rename configuration files if test -f "${OUTPUT}babel.config.js"; then - mv "${OUTPUT}babel.config.js" "${OUTPUT}babel.config.js.__exercism.bak" || true + echo "✔️ renaming babel.config.js in output so it can be replaced." + mv "${OUTPUT}babel.config.js" "${OUTPUT}babel.config.js.💥.bak" || true fi; if test -f "${OUTPUT}package.json"; then - mv "${OUTPUT}package.json" "${OUTPUT}package.json.__exercism.bak" || true + echo "✔️ renaming package.json in output so it can be replaced." + mv "${OUTPUT}package.json" "${OUTPUT}package.json.💥.bak" || true +fi; + +if test -f "${OUTPUT}tsconfig.json"; then + echo "✔️ renaming tsconfig.json in output so it can be replaced." + mv "${OUTPUT}tsconfig.json" "${OUTPUT}tsconfig.json.💥.bak" || true fi; if [[ "${OUTPUT}" =~ "$ROOT" ]]; then - echo "Test runnner root contains output directory. No need to turn output directory into a standalone package." + echo "" + echo "The output directory seems to be placed inside the test " + echo "runner root. This means the CLI tools we run will use the " + echo "configuration files as given by the test-runner for running " + echo "the tests, which is what we want. No need to turn the output " + echo "directory into a standalone package." + echo "" else - echo "Test runnner root does not contain output directory. Turning output directory into a standalone package." + echo "" + echo "The output directory is likely not placed inside the test " + echo "runner root. This means the CLI tools need configuration " + echo "files as given and understood by the test-runner for running " + echo "the tests. Will now turn the output directory into a " + echo "standalone package." + echo "" + + echo "✔️ .yarn cache from root to output" + cp -r "${ROOT}/.yarn" "${OUTPUT}" - # Turn into standalone package + echo "✔️ .yarnrc.yml from root to output" cp "${ROOT}/.yarnrc.yml" "${OUTPUT}/.yarnrc.yml" + + echo "✔️ .yarn.lock from root to output" cp "${ROOT}/yarn.lock" "${OUTPUT}/yarn.lock" + + echo "✔️ .pnp.cjs from root to output" cp "${ROOT}/.pnp.cjs" "${OUTPUT}/.pnp.cjs" + + echo "✔️ .pnp.loader.mjs from root to output" cp "${ROOT}/.pnp.loader.mjs" "${OUTPUT}/.pnp.loader.mjs" + + echo "✔️ babel.config.js from root to output" + cp "${ROOT}/babel.config.js" "${OUTPUT}babel.config.js" + + echo "✔️ package.json from root to output" cp "${ROOT}/package.json" "${OUTPUT}package.json" + + echo "✔️ tsconfig.json from root to output" + cp "${ROOT}/tsconfig.json" "${OUTPUT}tsconfig.json" + echo "" fi +# Put together the path to the test results file +result_file="${OUTPUT}results.json" +echo "The results of this run will be written to 'results.json'." +echo "👁️ ${result_file}" +echo "" +echo "╔═════════════════════════════════════════════════════════════╗" +echo " 🔧 Preparing test suite file(s) " +echo "╚═════════════════════════════════════════════════════════════╝" +echo "" + if test -f $configuration_file; then - echo "Using ${configuration_file} as base configuration" + echo "There is a configuration file in the expected .meta location " + echo "which will now be used to determine which test files to prep." + echo "👁️ ${configuration_file}" + echo "" + cat $configuration_file | jq -c '.files.test[]' | xargs -L 1 "$ROOT/bin/prepare.sh" ${OUTPUT} else if test -f $local_configuration_file; then - echo "Using ${local_configuration_file} as base configuration" + echo "There is a configuration file in the .exercism local " + echo "location which will now be used to determine which test " + echo "files to prep." + echo "👁️ ${local_configuration_file}" + echo "" + cat $local_configuration_file | jq -c '.files.test[]' | xargs -L 1 "$ROOT/bin/prepare.sh" ${OUTPUT} else test_file="${SLUG}.test.ts" - echo "No configuration given. Falling back to ${test_file}" - "$ROOT/bin/prepare.sh" ${OUTPUT} ${test_file} - fi; -fi; -if test -d "${OUTPUT}node_modules"; then - echo "Did not expect node_modules in output directory, but here we are" -fi; + echo "⚠️ No configuration file found. The test-runner will now " + echo " guess which test file(s) to prep based on the input." + echo "👁️ ${test_file}" + echo "" -# Put together the path to the test results file -result_file="${OUTPUT}results.json" + if test -f $test_file; then + "$ROOT/bin/prepare.sh" ${OUTPUT} ${test_file} + else + result="The submitted code cannot be ran by the test-runner. There is no configuration file inside the .meta (or .exercism) directory, and the fallback test file '${test_file}' does not exist. Please fix these issues and resubmit." + echo "{ \"version\": 1, \"status\": \"error\", \"message\": \"$result\" }" > $result_file + sed -Ei ':a;N;$!ba;s/\r{0,1}\n/\\n/g' $result_file -# Check yarn -if test -f "$ROOT/corepack.tgz"; then - echo "'$ROOT/corepack.tgz' found. Expect global yarn to be available." -fi; + echo "❌ could not run the test suite(s). A valid output exists:" + echo "${result}" + echo "---------------------------------------------------------------" + + # Test runner didn't fail! + exit 0 + fi + fi +fi + +echo "" +echo "╔═════════════════════════════════════════════════════════════╗" +echo " 🔧 Preparing test project " +echo "╚═════════════════════════════════════════════════════════════╝" +echo "" + +if test -d "${OUTPUT}node_modules"; then + echo "⚠️ Did not expect node_modules in output directory. This is likely an " + echo " issue with the given solution or it is old. These will be ignored." + echo "" +fi # In case it's not yet enabled +echo "✔️ enabling corepack" corepack enable yarn; -echo "Yarn version now: " -YARN_ENABLE_OFFLINE_MODE=1 corepack yarn --version +echo "✔️ yarn version now: $(YARN_ENABLE_OFFLINE_MODE=1 corepack yarn --version)" echo "" -echo "---------------------------------------------------------------" if test -f "${OUTPUT}package.json"; then + echo "✔️ standalone package found installing packages from cache" + echo "" ls -aln1 "$OUTPUT" - - echo "Standalone package found" #, installing packages from cache" - cd "${OUTPUT}" && pwd && YARN_ENABLE_NETWORK=false YARN_ENABLE_HARDENED_MODE=false YARN_ENABLE_OFFLINE_MODE=true YARN_ENABLE_GLOBAL_CACHE=false corepack yarn install --immutable - echo "---------------------------------------------------------------" + echo "" + cd "${OUTPUT}" && YARN_ENABLE_NETWORK=false YARN_ENABLE_HARDENED_MODE=false YARN_ENABLE_OFFLINE_MODE=true YARN_ENABLE_GLOBAL_CACHE=false corepack yarn install --immutable fi; +echo "" +echo "╔═════════════════════════════════════════════════════════════╗" +echo "║ ➤ Step 1/3: Build (tests: does it compile?) ║" +echo "╚═════════════════════════════════════════════════════════════╝" +echo "" + # Disable auto exit set +e @@ -201,12 +289,20 @@ set +e # cp -r "$ROOT/node_modules/@types" "$INPUT/node_modules" if test -f "${OUTPUT}tsconfig.json"; then - echo "Found tsconfig.json; disabling test compilation" - sed -i 's/, "\.meta\/\*"//' "${OUTPUT}tsconfig.json" - sed -i 's/"node_modules"/"node_modules", "*.test.ts", ".meta\/*"/' "${OUTPUT}tsconfig.json" + echo "✔️ found a tsconfig.json (as expected). Re-configuring." + + # replace "include": ["src"], + sed -i 's/"include": \["src"\],/"\/\/ include": ["src"],/' "${OUTPUT}tsconfig.json" + + # replace "exclude": ["test", "node_modules"] + sed -i 's/"exclude": \["test", "node_modules"\]/"exclude": ["test", "node_modules", ".meta\/*", "__typetests__\/*", "*.test.ts", "*.tst.ts"]/' "${OUTPUT}tsconfig.json" + + echo "👁️ ${OUTPUT}tsconfig.json" + cat "${OUTPUT}tsconfig.json" + echo "" fi; -echo "Running tsc" +echo "⚙️ corepack yarn run tsc" tsc_result="$( cd "${OUTPUT}" && YARN_ENABLE_OFFLINE_MODE=1 corepack yarn run tsc --noEmit 2>&1 )" test_exit=$? @@ -214,27 +310,40 @@ echo "$tsc_result" > $result_file sed -i 's/"/\\"/g' $result_file if test -f "${OUTPUT}tsconfig.json"; then - echo "Found tsconfig.json; enabling test compilation" - sed -i 's/\["\*"\]/["*", ".meta\/*"]/' "${OUTPUT}tsconfig.json" - sed -i 's/"node_modules", "\*\.test\.ts", "\.meta\/\*"/"node_modules"/' "${OUTPUT}tsconfig.json" + echo "✔️ found a tsconfig.json (as expected). Restoring." + + # replace "include": ["src"], + sed -i 's/"\/\/ include": \["src"\],/"include": ["src"],/' "${OUTPUT}tsconfig.json" + + # replace "exclude": ["test", "node_modules"] + sed -i 's/"exclude": \["test", "node_modules", ".meta\/*", "__typetests__\/*", "*.test.ts", "*.tst.ts"\]/"exclude": ["test", "node_modules"]/' "${OUTPUT}tsconfig.json" fi; -if [ $test_exit -eq 2 ] -then +if [ $test_exit -eq 2 ]; then + echo "" + echo "❌ tsc compilation failed" + echo "" + echo "If the solution previously contained configuration files, " + echo "they were disabled and now need to be restored." echo "" - echo "tsc compilation failed" - # Restore babel.config.js and package.json - if test -f "${OUTPUT}package.config.json"; then - unlink "${OUTPUT}package.config.json" + # Restore configuration files + if test -f "${OUTPUT}babel.config.js.💥.bak"; then + echo "✔️ restoring babel.config.js in output" + unlink "${OUTPUT}babel.config.js" + mv "${OUTPUT}babel.config.js.💥.bak" "${OUTPUT}babel.config.js" || true fi; - if test -f "${OUTPUT}babel.config.js.__exercism.bak"; then - mv "${OUTPUT}babel.config.js.__exercism.bak" "${OUTPUT}babel.config.js" || true + if test -f "${OUTPUT}package.json.💥.bak"; then + echo "✔️ restoring package.json in output" + unlink "${OUTPUT}package.json" + mv "${OUTPUT}package.json.💥.bak" "${OUTPUT}package.json" || true fi; - if test -f "${OUTPUT}package.json.__exercism.bak"; then - mv "${OUTPUT}package.json.__exercism.bak" "${OUTPUT}package.json" || true + if test -f "${OUTPUT}tsconfig.json.💥.bak"; then + echo "✔️ restoring tsconfig.json in output" + unlink "${OUTPUT}tsconfig.json" + mv "${OUTPUT}tsconfig.json.💥.bak" "${OUTPUT}tsconfig.json" || true fi; # Compose the message to show to the student @@ -247,22 +356,108 @@ then echo "{ \"version\": 1, \"status\": \"error\", \"message\": \"$tsc_result\" }" > $result_file sed -Ei ':a;N;$!ba;s/\r{0,1}\n/\\n/g' $result_file + echo "❌ tsc compilation failed with a valid output:" + echo "${tsc_result}" echo "" echo "---------------------------------------------------------------" - echo "Find the output at:" - echo $result_file + echo "The results of this run have been written to 'results.json'." + echo "👁️ ${result_file}" # Test runner didn't fail! exit 0 else echo "" - echo "tsc compilation success" + echo "✅ tsc compilation success" fi -echo "---------------------------------------------------------------" -echo "Running tests via jest" +echo "" +echo "╔═════════════════════════════════════════════════════════════╗" +echo "║ ➤ Step 2/3: Type tests (tests: are the types as expected?) ║" +echo "╚═════════════════════════════════════════════════════════════╝" +echo "" + +has_type_test=false + +if ls -U "${OUTPUT}/**/*.tst.ts" 1> /dev/null 2>&1; then + has_type_test=true + echo "✔️ type tests discovered." + corepack yarn tstyche --listFiles + + echo "" + echo "⚙️ corepack yarn tstyche" + cd "${OUTPUT}" && corepack yarn tstyche 2> "${OUTPUT}tstyche.stderr.txt" 1> "${OUTPUT}tstyche.stdout.txt" + + cat "${OUTPUT}tstyche.stdout.txt" + cat "${OUTPUT}tstyche.stderr.txt" + + # TODO: use results from tstyche +else + # TODO: check the config file to see if tstyche tests were expected or not + echo "✅ no type tests (*.tst.ts) discovered." +fi; + +echo "" +echo "╔═════════════════════════════════════════════════════════════╗" +echo "║ ➤ Step 3/3: Execution (tests: does the solution work?) ║" +echo "╚═════════════════════════════════════════════════════════════╝" +echo "" + +jest_tests=$(corepack yarn jest --listTests --passWithNoTests) || false + +if [ -z "${jest_tests}" ]; then + echo "✔️ no jest tests (*.test.ts) discovered." + if [ "$has_type_test" = true ]; then + # TODO: check the config file to see if jest tests were expected or not + echo "✔️ did run type tests, so this is fine." + + # TODO: use results from tstyche + runner_result="The type tests ran correctly. We are working on showing the individual tests results but for now, everything is fine!" + echo "{ \"version\": 1, \"status\": \"pass\", \"message\": \"$runner_result\" }" > $result_file + else + runner_result="The submitted code was not subjected to any type or executation tests. It did compile correctly, but somethign is wrong because at least one test was expected." + echo "{ \"version\": 1, \"status\": \"error\", \"message\": \"$runner_result\" }" > $result_file + sed -Ei ':a;N;$!ba;s/\r{0,1}\n/\\n/g' $result_file + fi + + echo "" + echo "If the solution previously contained configuration files, " + echo "they were disabled and now need to be restored." + echo "" + + # Restore configuration files + if test -f "${OUTPUT}babel.config.js.💥.bak"; then + echo "✔️ restoring babel.config.js in output" + unlink "${OUTPUT}babel.config.js" + mv "${OUTPUT}babel.config.js.💥.bak" "${OUTPUT}babel.config.js" || true + fi; + + if test -f "${OUTPUT}package.json.💥.bak"; then + echo "✔️ restoring package.json in output" + unlink "${OUTPUT}package.json" + mv "${OUTPUT}package.json.💥.bak" "${OUTPUT}package.json" || true + fi; + + if test -f "${OUTPUT}tsconfig.json.💥.bak"; then + echo "✔️ restoring tsconfig.json in output" + unlink "${OUTPUT}tsconfig.json" + mv "${OUTPUT}tsconfig.json.💥.bak" "${OUTPUT}tsconfig.json" || true + fi; + + echo "" + echo "---------------------------------------------------------------" + echo "The results of this run have been written to 'results.json'." + echo "👁️ ${result_file}" + + # Test runner didn't fail! + exit 0 +fi + +echo "✔️ jest tests (*.test.ts) discovered." +echo $jest_tests # Run tests +echo "" +echo "⚙️ corepack yarn jest <...>" cd "${OUTPUT}" && YARN_ENABLE_OFFLINE_MODE=1 corepack yarn run jest "${OUTPUT}*" \ --bail 1 \ --ci \ @@ -280,26 +475,42 @@ cd "${OUTPUT}" && YARN_ENABLE_OFFLINE_MODE=1 corepack yarn run jest "${OUTPUT}*" # Convert exit(1) (jest worked, but there are failing tests) to exit(0) test_exit=$? -# Restore babel.config.js and package.json -if test -f "${OUTPUT}package.config.json"; then - unlink "${OUTPUT}package.config.json" +if [ $test_exit -eq 1 ]; then + echo "❌ not all tests (*.test.ts) passed." +else + echo "✅ all tests (*.test.ts) passed." +fi; + +echo "" +echo "If the solution previously contained configuration files, " +echo "they were disabled and now need to be restored." +echo "" + +# Restore configuration files +if test -f "${OUTPUT}babel.config.js.💥.bak"; then + echo "✔️ restoring babel.config.js in output" + unlink "${OUTPUT}babel.config.js" + mv "${OUTPUT}babel.config.js.💥.bak" "${OUTPUT}babel.config.js" || true fi; -if test -f "${OUTPUT}babel.config.js.__exercism.bak"; then - mv "${OUTPUT}babel.config.js.__exercism.bak" "${OUTPUT}babel.config.js" || true +if test -f "${OUTPUT}package.json.💥.bak"; then + echo "✔️ restoring package.json in output" + unlink "${OUTPUT}package.json" + mv "${OUTPUT}package.json.💥.bak" "${OUTPUT}package.json" || true fi; -if test -f "${OUTPUT}package.json.__exercism.bak"; then - mv "${OUTPUT}package.json.__exercism.bak" "${OUTPUT}package.json" || true +if test -f "${OUTPUT}tsconfig.json.💥.bak"; then + echo "✔️ restoring tsconfig.json in output" + unlink "${OUTPUT}tsconfig.json" + mv "${OUTPUT}tsconfig.json.💥.bak" "${OUTPUT}tsconfig.json" || true fi; echo "" echo "---------------------------------------------------------------" -echo "Find the output at:" -echo $result_file +echo "The results of this run have been written to 'results.json'." +echo "👁️ ${result_file}" -if [ $test_exit -eq 1 ] -then +if [ $test_exit -eq 1 ]; then exit 0 else exit $test_exit diff --git a/package.json b/package.json index 73a501a..3f82cd2 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "core-js": "^3.37.1", "jest": "^29.7.0", "shelljs": "^0.8.5", + "tstyche": "^2.1.1", "typescript": "~5.5.4" }, "devDependencies": { diff --git a/test/fixtures/tstyche/documentation/__typetests__/docs.tst.ts b/test/fixtures/tstyche/documentation/__typetests__/docs.tst.ts new file mode 100644 index 0000000..5d2266d --- /dev/null +++ b/test/fixtures/tstyche/documentation/__typetests__/docs.tst.ts @@ -0,0 +1,20 @@ +import { expect, test } from "tstyche"; + +function firstItem(target: Array): T | undefined { + return target[0]; +} + +test("first item requires a parameter", () => { + expect(firstItem(["a", "b", "c"])).type.toBe(); + + // @ts-expect-error + expect(firstItem()).type.toRaiseError("Expected 1 argument"); +}); + +function secondItem(target: Array): T | undefined { + return target[1]; +} + +test("handles numbers", () => { + expect(secondItem([1, 2, 3])).type.toBe(); +}); \ No newline at end of file diff --git a/test/fixtures/tstyche/documentation/__typetests__/tsconfig.json b/test/fixtures/tstyche/documentation/__typetests__/tsconfig.json new file mode 100644 index 0000000..1597b94 --- /dev/null +++ b/test/fixtures/tstyche/documentation/__typetests__/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "noEmit": true, + "strict": true, + "types": [] + }, + "include": ["./"], + "exclude": [] +} \ No newline at end of file diff --git a/test/fixtures/tstyche/documentation/tsconfig.json b/test/fixtures/tstyche/documentation/tsconfig.json new file mode 100644 index 0000000..dc7d845 --- /dev/null +++ b/test/fixtures/tstyche/documentation/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "exclude": ["./__typetests__"] +} diff --git a/test/fixtures/tstyche/fire/__typetests__/fire.tst.ts b/test/fixtures/tstyche/fire/__typetests__/fire.tst.ts new file mode 100644 index 0000000..1046f7c --- /dev/null +++ b/test/fixtures/tstyche/fire/__typetests__/fire.tst.ts @@ -0,0 +1,14 @@ +import { test, expect, describe } from 'tstyche' +import type { MethodLikeKeys } from '../fire.js' + +interface Sample { + description: string + getLength: () => number + getWidth?: () => number +} + +describe('fire', () => { + test('all method keys are found', () => { + expect>().type.toBe<'getLength' | 'getWidth'>() + }) +}) diff --git a/test/fixtures/tstyche/fire/__typetests__/tsconfig.json b/test/fixtures/tstyche/fire/__typetests__/tsconfig.json new file mode 100644 index 0000000..1597b94 --- /dev/null +++ b/test/fixtures/tstyche/fire/__typetests__/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "noEmit": true, + "strict": true, + "types": [] + }, + "include": ["./"], + "exclude": [] +} \ No newline at end of file diff --git a/test/fixtures/tstyche/fire/fire.ts b/test/fixtures/tstyche/fire/fire.ts new file mode 100644 index 0000000..508bb00 --- /dev/null +++ b/test/fixtures/tstyche/fire/fire.ts @@ -0,0 +1,5 @@ +type MethodLike = (...args: any) => any; + +export type MethodLikeKeys = keyof { + [K in keyof T as T[K] extends MethodLike ? K : never]: T[K]; +}; \ No newline at end of file diff --git a/test/fixtures/tstyche/fire/tsconfig.json b/test/fixtures/tstyche/fire/tsconfig.json new file mode 100644 index 0000000..dc7d845 --- /dev/null +++ b/test/fixtures/tstyche/fire/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "exclude": ["./__typetests__"] +} diff --git a/test/fixtures/tstyche/firefought/__typetests__/fire.tst.ts b/test/fixtures/tstyche/firefought/__typetests__/fire.tst.ts new file mode 100644 index 0000000..730404d --- /dev/null +++ b/test/fixtures/tstyche/firefought/__typetests__/fire.tst.ts @@ -0,0 +1,14 @@ +import { describe, test, expect } from "tstyche"; +import type { MethodLikeKeys } from "../fire.js"; + +interface Sample { + description: string; + getLength: () => number; + getWidth?: () => number; +} + +describe('fire', () => { + test('all method keys are found', () => { + expect>().type.toBe<"getLength" | "getWidth">(); + }) +}) diff --git a/test/fixtures/tstyche/firefought/__typetests__/tsconfig.json b/test/fixtures/tstyche/firefought/__typetests__/tsconfig.json new file mode 100644 index 0000000..1597b94 --- /dev/null +++ b/test/fixtures/tstyche/firefought/__typetests__/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "noEmit": true, + "strict": true, + "types": [] + }, + "include": ["./"], + "exclude": [] +} \ No newline at end of file diff --git a/test/fixtures/tstyche/firefought/fire.ts b/test/fixtures/tstyche/firefought/fire.ts new file mode 100644 index 0000000..dc52aef --- /dev/null +++ b/test/fixtures/tstyche/firefought/fire.ts @@ -0,0 +1,5 @@ +type MethodLike = (...args: any) => any; + +export type MethodLikeKeys = keyof { + [K in keyof T as Required[K] extends MethodLike ? K : never]: T[K]; +}; \ No newline at end of file diff --git a/test/fixtures/tstyche/firefought/tsconfig.json b/test/fixtures/tstyche/firefought/tsconfig.json new file mode 100644 index 0000000..dc7d845 --- /dev/null +++ b/test/fixtures/tstyche/firefought/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "exclude": ["./__typetests__"] +} diff --git a/yarn.lock b/yarn.lock index 6eb7e75..9e81407 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1546,6 +1546,7 @@ __metadata: prettier: "npm:^3.3.3" rimraf: "npm:^6.0.1" shelljs: "npm:^0.8.5" + tstyche: "npm:^2.1.1" typescript: "npm:~5.5.4" bin: typescript-test-runner: bin/run.sh @@ -6274,6 +6275,20 @@ __metadata: languageName: node linkType: hard +"tstyche@npm:^2.1.1": + version: 2.1.1 + resolution: "tstyche@npm:2.1.1" + peerDependencies: + typescript: 4.x || 5.x + peerDependenciesMeta: + typescript: + optional: true + bin: + tstyche: ./build/bin.js + checksum: 10/f30e7d782e51c262528ededf383c9daf39af8dea063d483667e3ff9f4800434891589c294c4b4f69802dd06daf8fb1d2a10553316d2f4631ba1413d3e48dab81 + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0"