chore: lint + bump deps

This commit is contained in:
liyasthomas
2021-11-04 18:23:50 +05:30
parent ad76d100ee
commit 9e74a8c2e7
32 changed files with 1248 additions and 1265 deletions

View File

@@ -23,7 +23,7 @@
"lint-staged": "^11.2.6" "lint-staged": "^11.2.6"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^13.2.1", "@commitlint/cli": "^14.1.0",
"@commitlint/config-conventional": "^13.2.0" "@commitlint/config-conventional": "^14.1.0"
} }
} }

View File

@@ -18,9 +18,7 @@ module.exports = {
"plugin:prettier/recommended", "plugin:prettier/recommended",
"plugin:nuxt/recommended", "plugin:nuxt/recommended",
], ],
ignorePatterns: [ ignorePatterns: ["helpers/backend/graphql.ts"],
"helpers/backend/graphql.ts"
],
plugins: ["vue", "prettier"], plugins: ["vue", "prettier"],
// add your custom rules here // add your custom rules here
rules: { rules: {
@@ -43,8 +41,12 @@ module.exports = {
"vue/multiline-html-element-content-newline": "off", "vue/multiline-html-element-content-newline": "off",
"vue/require-default-prop": "warn", "vue/require-default-prop": "warn",
"vue/require-prop-types": "warn", "vue/require-prop-types": "warn",
"vue/multi-word-component-names": "off",
"prettier/prettier": ["warn", { semi: false }], "prettier/prettier": ["warn", { semi: false }],
"import/no-named-as-default": "off", "import/no-named-as-default": "off",
"import/prefer-default-export": "off",
"import/no-named-as-default-member": "off",
"import/default": "off",
"no-undef": "off", "no-undef": "off",
// localStorage block // localStorage block
"no-restricted-globals": [ "no-restricted-globals": [

View File

@@ -1,5 +1,10 @@
module.exports = { module.exports = {
extends: ["stylelint-config-standard", "stylelint-config-prettier"], extends: [
"stylelint-config-standard",
"stylelint-config-prettier",
"stylelint-config-standard-scss",
],
defaultSeverity: "warning",
// add your custom config here // add your custom config here
// https://stylelint.io/user-guide/configuration // https://stylelint.io/user-guide/configuration
rules: { rules: {
@@ -19,5 +24,7 @@ module.exports = {
], ],
"declaration-block-trailing-semicolon": null, "declaration-block-trailing-semicolon": null,
"no-descending-specificity": null, "no-descending-specificity": null,
"selector-class-pattern": null,
"selector-id-pattern": null,
}, },
} }

View File

@@ -69,11 +69,11 @@ body {
@keyframes fade { @keyframes fade {
0% { 0% {
opacity: 0; @apply opacity-0;
} }
100% { 100% {
opacity: 1; @apply opacity-100;
} }
} }
@@ -182,10 +182,6 @@ a {
@apply max-h-46; @apply max-h-46;
@apply items-stretch; @apply items-stretch;
@apply overflow-y-auto; @apply overflow-y-auto;
// &::-webkit-scrollbar {
// @apply hidden;
// }
} }
hr { hr {

View File

@@ -1,374 +1,245 @@
@mixin baseTheme { @mixin base-theme {
--font-sans: "Inter", sans-serif; --font-sans: "Inter", sans-serif;
--font-mono: "Roboto Mono", monospace; --font-mono: "Roboto Mono", monospace;
--font-icon: "Material Icons"; --font-icon: "Material Icons";
} }
@mixin darkTheme { @mixin dark-theme {
// Background color
--primary-color: theme("colors.true-gray.900"); --primary-color: theme("colors.true-gray.900");
// Light Background color
--primary-light-color: theme("colors.dark.600"); --primary-light-color: theme("colors.dark.600");
// Dark Background color
--primary-dark-color: theme("colors.true-gray.800"); --primary-dark-color: theme("colors.true-gray.800");
// Text color
--secondary-color: theme("colors.true-gray.400"); --secondary-color: theme("colors.true-gray.400");
// Light Text color
--secondary-light-color: theme("colors.true-gray.500"); --secondary-light-color: theme("colors.true-gray.500");
// Dark Text color
--secondary-dark-color: theme("colors.true-gray.100"); --secondary-dark-color: theme("colors.true-gray.100");
// Border color
--divider-color: theme("colors.true-gray.800"); --divider-color: theme("colors.true-gray.800");
// Light Border color
--divider-light-color: theme("colors.dark.500"); --divider-light-color: theme("colors.dark.500");
// Dark Border color
--divider-dark-color: theme("colors.dark.300"); --divider-dark-color: theme("colors.dark.300");
// Error color
--error-color: theme("colors.warm-gray.800"); --error-color: theme("colors.warm-gray.800");
// Tooltip color
--tooltip-color: theme("colors.true-gray.100"); --tooltip-color: theme("colors.true-gray.100");
// Popover color
--popover-color: theme("colors.dark.700"); --popover-color: theme("colors.dark.700");
// Editor theme
--editor-theme: "merbivore_soft"; --editor-theme: "merbivore_soft";
} }
@mixin lightTheme { @mixin light-theme {
// Background color
--primary-color: theme("colors.white"); --primary-color: theme("colors.white");
// Light Background color
--primary-light-color: theme("colors.true-gray.50"); --primary-light-color: theme("colors.true-gray.50");
// Dark Background color
--primary-dark-color: theme("colors.true-gray.100"); --primary-dark-color: theme("colors.true-gray.100");
// Text color
--secondary-color: theme("colors.true-gray.500"); --secondary-color: theme("colors.true-gray.500");
// Light Text color
--secondary-light-color: theme("colors.true-gray.400"); --secondary-light-color: theme("colors.true-gray.400");
// Dark Text color
--secondary-dark-color: theme("colors.true-gray.900"); --secondary-dark-color: theme("colors.true-gray.900");
// Border color
--divider-color: theme("colors.true-gray.200"); --divider-color: theme("colors.true-gray.200");
// Light Border color
--divider-light-color: theme("colors.true-gray.100"); --divider-light-color: theme("colors.true-gray.100");
// Dark Border color
--divider-dark-color: theme("colors.true-gray.300"); --divider-dark-color: theme("colors.true-gray.300");
// Error color
--error-color: theme("colors.yellow.100"); --error-color: theme("colors.yellow.100");
// Tooltip color
--tooltip-color: theme("colors.true-gray.800"); --tooltip-color: theme("colors.true-gray.800");
// Popover color
--popover-color: theme("colors.white"); --popover-color: theme("colors.white");
// Editor theme
--editor-theme: "textmate"; --editor-theme: "textmate";
} }
@mixin blackTheme { @mixin black-theme {
// Background color
--primary-color: theme("colors.dark.900"); --primary-color: theme("colors.dark.900");
// Light Background color
--primary-light-color: theme("colors.true-gray.900"); --primary-light-color: theme("colors.true-gray.900");
// Dark Background color
--primary-dark-color: theme("colors.dark.800"); --primary-dark-color: theme("colors.dark.800");
// Text color
--secondary-color: theme("colors.true-gray.400"); --secondary-color: theme("colors.true-gray.400");
// Light Text color
--secondary-light-color: theme("colors.true-gray.500"); --secondary-light-color: theme("colors.true-gray.500");
// Dark Text color
--secondary-dark-color: theme("colors.true-gray.100"); --secondary-dark-color: theme("colors.true-gray.100");
// Border color
--divider-color: theme("colors.true-gray.800"); --divider-color: theme("colors.true-gray.800");
// Light Border color
--divider-light-color: theme("colors.dark.700"); --divider-light-color: theme("colors.dark.700");
// Dark Border color
--divider-dark-color: theme("colors.dark.300"); --divider-dark-color: theme("colors.dark.300");
// Error color
--error-color: theme("colors.warm-gray.900"); --error-color: theme("colors.warm-gray.900");
// Tooltip color
--tooltip-color: theme("colors.true-gray.100"); --tooltip-color: theme("colors.true-gray.100");
// Popover color
--popover-color: theme("colors.dark.700"); --popover-color: theme("colors.dark.700");
// Editor theme
--editor-theme: "twilight"; --editor-theme: "twilight";
} }
@mixin greenTheme { @mixin green-theme {
// Accent color
--accent-color: theme("colors.green.500"); --accent-color: theme("colors.green.500");
// Light Accent color
--accent-light-color: theme("colors.green.400"); --accent-light-color: theme("colors.green.400");
// Dark Accent color
--accent-dark-color: theme("colors.green.600"); --accent-dark-color: theme("colors.green.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.green.200"); --gradient-from-color: theme("colors.green.200");
// Gradient via
--gradient-via-color: theme("colors.green.400"); --gradient-via-color: theme("colors.green.400");
// Gradient to
--gradient-to-color: theme("colors.green.600"); --gradient-to-color: theme("colors.green.600");
} }
@mixin tealTheme { @mixin teal-theme {
// Accent color
--accent-color: theme("colors.teal.500"); --accent-color: theme("colors.teal.500");
// Light Accent color
--accent-light-color: theme("colors.teal.400"); --accent-light-color: theme("colors.teal.400");
// Dark Accent color
--accent-dark-color: theme("colors.teal.600"); --accent-dark-color: theme("colors.teal.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.teal.200"); --gradient-from-color: theme("colors.teal.200");
// Gradient via
--gradient-via-color: theme("colors.teal.400"); --gradient-via-color: theme("colors.teal.400");
// Gradient to
--gradient-to-color: theme("colors.teal.600"); --gradient-to-color: theme("colors.teal.600");
} }
@mixin blueTheme { @mixin blue-theme {
// Accent color
--accent-color: theme("colors.blue.500"); --accent-color: theme("colors.blue.500");
// Light Accent color
--accent-light-color: theme("colors.blue.400"); --accent-light-color: theme("colors.blue.400");
// Dark Accent color
--accent-dark-color: theme("colors.blue.600"); --accent-dark-color: theme("colors.blue.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.blue.200"); --gradient-from-color: theme("colors.blue.200");
// Gradient via
--gradient-via-color: theme("colors.blue.400"); --gradient-via-color: theme("colors.blue.400");
// Gradient to
--gradient-to-color: theme("colors.blue.600"); --gradient-to-color: theme("colors.blue.600");
} }
@mixin indigoTheme { @mixin indigo-theme {
// Accent color
--accent-color: theme("colors.indigo.500"); --accent-color: theme("colors.indigo.500");
// Light Accent color
--accent-light-color: theme("colors.indigo.400"); --accent-light-color: theme("colors.indigo.400");
// Dark Accent color
--accent-dark-color: theme("colors.indigo.600"); --accent-dark-color: theme("colors.indigo.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.indigo.200"); --gradient-from-color: theme("colors.indigo.200");
// Gradient via
--gradient-via-color: theme("colors.indigo.400"); --gradient-via-color: theme("colors.indigo.400");
// Gradient to
--gradient-to-color: theme("colors.indigo.600"); --gradient-to-color: theme("colors.indigo.600");
} }
@mixin purpleTheme { @mixin purple-theme {
// Accent color
--accent-color: theme("colors.purple.500"); --accent-color: theme("colors.purple.500");
// Light Accent color
--accent-light-color: theme("colors.purple.400"); --accent-light-color: theme("colors.purple.400");
// Dark Accent color
--accent-dark-color: theme("colors.purple.600"); --accent-dark-color: theme("colors.purple.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.purple.200"); --gradient-from-color: theme("colors.purple.200");
// Gradient via
--gradient-via-color: theme("colors.purple.400"); --gradient-via-color: theme("colors.purple.400");
// Gradient to
--gradient-to-color: theme("colors.purple.600"); --gradient-to-color: theme("colors.purple.600");
} }
@mixin yellowTheme { @mixin yellow-theme {
// Accent color
--accent-color: theme("colors.yellow.500"); --accent-color: theme("colors.yellow.500");
// Light Accent color
--accent-light-color: theme("colors.yellow.400"); --accent-light-color: theme("colors.yellow.400");
// Dark Accent color
--accent-dark-color: theme("colors.yellow.600"); --accent-dark-color: theme("colors.yellow.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.yellow.200"); --gradient-from-color: theme("colors.yellow.200");
// Gradient via
--gradient-via-color: theme("colors.yellow.400"); --gradient-via-color: theme("colors.yellow.400");
// Gradient to
--gradient-to-color: theme("colors.yellow.600"); --gradient-to-color: theme("colors.yellow.600");
} }
@mixin orangeTheme { @mixin orange-theme {
// Accent color
--accent-color: theme("colors.orange.500"); --accent-color: theme("colors.orange.500");
// Light Accent color
--accent-light-color: theme("colors.orange.400"); --accent-light-color: theme("colors.orange.400");
// Dark Accent color
--accent-dark-color: theme("colors.orange.600"); --accent-dark-color: theme("colors.orange.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.orange.200"); --gradient-from-color: theme("colors.orange.200");
// Gradient via
--gradient-via-color: theme("colors.orange.400"); --gradient-via-color: theme("colors.orange.400");
// Gradient to
--gradient-to-color: theme("colors.orange.600"); --gradient-to-color: theme("colors.orange.600");
} }
@mixin redTheme { @mixin red-theme {
// Accent color
--accent-color: theme("colors.red.500"); --accent-color: theme("colors.red.500");
// Light Accent color
--accent-light-color: theme("colors.red.400"); --accent-light-color: theme("colors.red.400");
// Dark Accent color
--accent-dark-color: theme("colors.red.600"); --accent-dark-color: theme("colors.red.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.red.200"); --gradient-from-color: theme("colors.red.200");
// Gradient via
--gradient-via-color: theme("colors.red.400"); --gradient-via-color: theme("colors.red.400");
// Gradient to
--gradient-to-color: theme("colors.red.600"); --gradient-to-color: theme("colors.red.600");
} }
@mixin pinkTheme { @mixin pink-theme {
// Accent color
--accent-color: theme("colors.pink.500"); --accent-color: theme("colors.pink.500");
// Light Accent color
--accent-light-color: theme("colors.pink.400"); --accent-light-color: theme("colors.pink.400");
// Dark Accent color
--accent-dark-color: theme("colors.pink.600"); --accent-dark-color: theme("colors.pink.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white"); --accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.pink.200"); --gradient-from-color: theme("colors.pink.200");
// Gradient via
--gradient-via-color: theme("colors.pink.400"); --gradient-via-color: theme("colors.pink.400");
// Gradient to
--gradient-to-color: theme("colors.pink.600"); --gradient-to-color: theme("colors.pink.600");
} }
:root { :root {
@include baseTheme; @include base-theme;
@include darkTheme; @include dark-theme;
@include greenTheme; @include green-theme;
} }
:root.light { :root.light {
@include lightTheme; @include light-theme;
} }
:root.dark { :root.dark {
@include darkTheme; @include dark-theme;
} }
:root.black { :root.black {
@include blackTheme; @include black-theme;
} }
:root[data-accent="blue"] { :root[data-accent="blue"] {
@include blueTheme; @include blue-theme;
} }
:root[data-accent="green"] { :root[data-accent="green"] {
@include greenTheme; @include green-theme;
} }
:root[data-accent="teal"] { :root[data-accent="teal"] {
@include tealTheme; @include teal-theme;
} }
:root[data-accent="indigo"] { :root[data-accent="indigo"] {
@include indigoTheme; @include indigo-theme;
} }
:root[data-accent="purple"] { :root[data-accent="purple"] {
@include purpleTheme; @include purple-theme;
} }
:root[data-accent="orange"] { :root[data-accent="orange"] {
@include orangeTheme; @include orange-theme;
} }
:root[data-accent="pink"] { :root[data-accent="pink"] {
@include pinkTheme; @include pink-theme;
} }
:root[data-accent="red"] { :root[data-accent="red"] {
@include redTheme; @include red-theme;
} }
:root[data-accent="yellow"] { :root[data-accent="yellow"] {
@include yellowTheme; @include yellow-theme;
} }
@mixin fontSmall { @mixin font-small {
// Font size
--body-font-size: 0.75rem; --body-font-size: 0.75rem;
// Line height
--body-line-height: 1rem; --body-line-height: 1rem;
// Upper primary sticky fold
--upper-primary-sticky-fold: 4.125rem; --upper-primary-sticky-fold: 4.125rem;
// Upper secondary sticky fold
--upper-secondary-sticky-fold: 6.125rem; --upper-secondary-sticky-fold: 6.125rem;
// Upper tertiary sticky fold
--upper-tertiary-sticky-fold: 8.188rem; --upper-tertiary-sticky-fold: 8.188rem;
// Lower primary sticky fold
--lower-primary-sticky-fold: 3rem; --lower-primary-sticky-fold: 3rem;
// Lower secondary sticky fold
--lower-secondary-sticky-fold: 5rem; --lower-secondary-sticky-fold: 5rem;
// Sidebar primary sticky fold
--sidebar-primary-sticky-fold: 2rem; --sidebar-primary-sticky-fold: 2rem;
// Sidebar secondary sticky fold
--sidebar-secondary-sticky-fold: 4rem; --sidebar-secondary-sticky-fold: 4rem;
} }
@mixin fontMedium { @mixin font-medium {
// Font size
--body-font-size: 0.875rem; --body-font-size: 0.875rem;
// Line height
--body-line-height: 1.25rem; --body-line-height: 1.25rem;
// Upper primary sticky fold
--upper-primary-sticky-fold: 4.375rem; --upper-primary-sticky-fold: 4.375rem;
// Upper secondary sticky fold
--upper-secondary-sticky-fold: 6.625rem; --upper-secondary-sticky-fold: 6.625rem;
// Upper tertiary sticky fold
--upper-tertiary-sticky-fold: 8.813rem; --upper-tertiary-sticky-fold: 8.813rem;
// Lower primary sticky fold
--lower-primary-sticky-fold: 3.25rem; --lower-primary-sticky-fold: 3.25rem;
// Lower secondary sticky fold
--lower-secondary-sticky-fold: 5.5rem; --lower-secondary-sticky-fold: 5.5rem;
// Sidebar primary sticky fold
--sidebar-primary-sticky-fold: 2.25rem; --sidebar-primary-sticky-fold: 2.25rem;
// Sidebar secondary sticky fold
--sidebar-secondary-sticky-fold: 4.5rem; --sidebar-secondary-sticky-fold: 4.5rem;
} }
@mixin fontLarge { @mixin font-large {
// Font size
--body-font-size: 1rem; --body-font-size: 1rem;
// Line height
--body-line-height: 1.5rem; --body-line-height: 1.5rem;
// Upper primary sticky fold
--upper-primary-sticky-fold: 4.625rem; --upper-primary-sticky-fold: 4.625rem;
// Upper secondary sticky fold
--upper-secondary-sticky-fold: 7.125rem; --upper-secondary-sticky-fold: 7.125rem;
// Upper tertiary sticky fold
--upper-tertiary-sticky-fold: 9.5rem; --upper-tertiary-sticky-fold: 9.5rem;
// Lower primary sticky fold
--lower-primary-sticky-fold: 3.5rem; --lower-primary-sticky-fold: 3.5rem;
// Lower secondary sticky fold
--lower-secondary-sticky-fold: 6rem; --lower-secondary-sticky-fold: 6rem;
// Sidebar primary sticky fold
--sidebar-primary-sticky-fold: 2.5rem; --sidebar-primary-sticky-fold: 2.5rem;
// Sidebar secondary sticky fold
--sidebar-secondary-sticky-fold: 5rem; --sidebar-secondary-sticky-fold: 5rem;
} }
:root[data-font-size="small"] { :root[data-font-size="small"] {
@include fontSmall; @include font-small;
} }
:root[data-font-size="medium"] { :root[data-font-size="medium"] {
@include fontMedium; @include font-medium;
} }
:root[data-font-size="large"] { :root[data-font-size="large"] {
@include fontLarge; @include font-large;
} }

View File

@@ -146,7 +146,7 @@ defineActionHandler("modals.search.toggle", () => {
showSearch.value = !showSearch.value showSearch.value = !showSearch.value
}) })
onMounted(async () => { onMounted(() => {
window.addEventListener("online", () => { window.addEventListener("online", () => {
isOnLine.value = true isOnLine.value = true
}) })

View File

@@ -194,7 +194,7 @@ export default defineComponent({
this.debouncer() this.debouncer()
}, },
}, },
mounted() { created() {
if (process.browser) { if (process.browser) {
this.worker = this.$worker.createRejexWorker() this.worker = this.$worker.createRejexWorker()
this.worker.addEventListener("message", this.workerResponseHandler) this.worker.addEventListener("message", this.workerResponseHandler)

View File

@@ -268,7 +268,7 @@ export default defineComponent({
else this.$refs.versionOptions.tippy().enable() else this.$refs.versionOptions.tippy().enable()
}, },
}, },
mounted() { created() {
if (process.browser) { if (process.browser) {
this.worker = this.$worker.createRejexWorker() this.worker = this.$worker.createRejexWorker()
this.worker.addEventListener("message", this.workerResponseHandler) this.worker.addEventListener("message", this.workerResponseHandler)

View File

@@ -126,7 +126,7 @@ export default defineComponent({
this.debouncer() this.debouncer()
}, },
}, },
mounted() { created() {
if (process.browser) { if (process.browser) {
this.worker = this.$worker.createRejexWorker() this.worker = this.$worker.createRejexWorker()
this.worker.addEventListener("message", this.workerResponseHandler) this.worker.addEventListener("message", this.workerResponseHandler)

View File

@@ -272,7 +272,7 @@ export default defineComponent({
deep: true, deep: true,
}, },
}, },
mounted() { created() {
if (process.browser) { if (process.browser) {
this.worker = this.$worker.createRejexWorker() this.worker = this.$worker.createRejexWorker()
this.worker.addEventListener("message", this.workerResponseHandler) this.worker.addEventListener("message", this.workerResponseHandler)

View File

@@ -402,6 +402,9 @@ import {
TeamInvitationAddedDocument, TeamInvitationAddedDocument,
TeamInvitationRemovedDocument, TeamInvitationRemovedDocument,
TeamMemberRole, TeamMemberRole,
GetPendingInvitesDocument,
GetPendingInvitesQuery,
GetPendingInvitesQueryVariables,
} from "../../helpers/backend/graphql" } from "../../helpers/backend/graphql"
import { import {
createTeamInvitation, createTeamInvitation,
@@ -409,11 +412,6 @@ import {
revokeTeamInvitation, revokeTeamInvitation,
} from "../../helpers/backend/mutations/TeamInvitation" } from "../../helpers/backend/mutations/TeamInvitation"
import { GQLError, useGQLQuery } from "~/helpers/backend/GQLClient" import { GQLError, useGQLQuery } from "~/helpers/backend/GQLClient"
import {
GetPendingInvitesDocument,
GetPendingInvitesQuery,
GetPendingInvitesQueryVariables,
} from "~/helpers/backend/graphql"
const { const {
$toast, $toast,

View File

@@ -190,20 +190,17 @@ function setupEnvironmentsPersistence() {
} }
function setupSelectedEnvPersistence() { function setupSelectedEnvPersistence() {
const selectedEnvIndex = const selectedEnvIndex = pipe(
pipe( // Value from local storage can be nullable
// Value from local storage can be nullable O.fromNullable(window.localStorage.getItem("selectedEnvIndex")),
O.fromNullable( O.map(parseInt), // If not null, parse to integer
window.localStorage.getItem("selectedEnvIndex") O.chain(
), O.fromPredicate(
O.map(parseInt), // If not null, parse to integer Number.isInteger // Check if the number is proper int (not NaN)
O.chain( )
O.fromPredicate( ),
Number.isInteger // Check if the number is proper int (not NaN) O.getOrElse(() => -1) // If all the above conditions pass, we are good, else set default value (-1)
) )
),
O.getOrElse(() => -1) // If all the above conditions pass, we are good, else set default value (-1)
)
setCurrentEnvironment(selectedEnvIndex) setCurrentEnvironment(selectedEnvIndex)

View File

@@ -17,11 +17,11 @@
"start": "nuxt start", "start": "nuxt start",
"generate": "nuxt generate --modern", "generate": "nuxt generate --modern",
"analyze": "npx nuxt build -a", "analyze": "npx nuxt build -a",
"lint:script": "eslint --ext .ts,.js,.vue --ignore-path .gitignore", "lint:script": "eslint --ext .ts,.js,.vue --ignore-path .gitignore .",
"lint:style": "stylelint **/*.{css,scss,vue} --ignore-path .gitignore", "lint:style": "stylelint **/*.{css,scss} --ignore-path .gitignore",
"lint": "pnpm run lint:script && pnpm run lint:style", "lint": "pnpm run lint:script && pnpm run lint:style",
"lintfix:script": "eslint --fix --ext .ts,.js,.vue --ignore-path .gitignore", "lintfix:script": "eslint --fix --ext .ts,.js,.vue --ignore-path .gitignore .",
"lintfix:style": "stylelint --fix **/*.{css,scss,vue} --ignore-path .gitignore", "lintfix:style": "stylelint --fix **/*.{css,scss} --ignore-path .gitignore",
"lintfix": "pnpm run lintfix:script && pnpm run lintfix:style", "lintfix": "pnpm run lintfix:script && pnpm run lintfix:style",
"test": "jest", "test": "jest",
"do-dev": "pnpm run dev", "do-dev": "pnpm run dev",
@@ -38,7 +38,7 @@
"@nuxtjs/axios": "^5.13.6", "@nuxtjs/axios": "^5.13.6",
"@nuxtjs/composition-api": "^0.29.3", "@nuxtjs/composition-api": "^0.29.3",
"@nuxtjs/gtm": "^2.4.0", "@nuxtjs/gtm": "^2.4.0",
"@nuxtjs/i18n": "^7.1.0", "@nuxtjs/i18n": "^7.2.0",
"@nuxtjs/robots": "^2.5.0", "@nuxtjs/robots": "^2.5.0",
"@nuxtjs/sitemap": "^2.4.0", "@nuxtjs/sitemap": "^2.4.0",
"@nuxtjs/toast": "^3.3.1", "@nuxtjs/toast": "^3.3.1",
@@ -50,7 +50,7 @@
"axios": "^0.24.0", "axios": "^0.24.0",
"codemirror": "^5.63.3", "codemirror": "^5.63.3",
"codemirror-theme-github": "^1.0.0", "codemirror-theme-github": "^1.0.0",
"core-js": "^3.19.0", "core-js": "^3.19.1",
"esprima": "^4.0.1", "esprima": "^4.0.1",
"firebase": "^9.2.0", "firebase": "^9.2.0",
"fp-ts": "^2.11.5", "fp-ts": "^2.11.5",
@@ -72,7 +72,7 @@
"socket.io-client-v4": "npm:socket.io-client@^4.3.2", "socket.io-client-v4": "npm:socket.io-client@^4.3.2",
"socketio-wildcard": "^2.0.0", "socketio-wildcard": "^2.0.0",
"splitpanes": "^2.3.8", "splitpanes": "^2.3.8",
"subscriptions-transport-ws": "^0.9.19", "subscriptions-transport-ws": "^0.11.0",
"tern": "^0.24.3", "tern": "^0.24.3",
"uuid": "8.3.2", "uuid": "8.3.2",
"vue-apollo": "^3.0.8", "vue-apollo": "^3.0.8",
@@ -88,12 +88,10 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.16.0", "@babel/core": "^7.16.0",
"@babel/preset-env": "^7.16.0", "@babel/preset-env": "^7.16.0",
"@commitlint/cli": "^13.2.1",
"@commitlint/config-conventional": "^13.2.0",
"@graphql-codegen/add": "^3.1.0", "@graphql-codegen/add": "^3.1.0",
"@graphql-codegen/cli": "2.2.0", "@graphql-codegen/cli": "2.2.2",
"@graphql-codegen/typed-document-node": "^2.2.0", "@graphql-codegen/typed-document-node": "^2.2.0",
"@graphql-codegen/typescript": "2.2.2", "@graphql-codegen/typescript": "2.3.0",
"@graphql-codegen/typescript-operations": "^2.2.0", "@graphql-codegen/typescript-operations": "^2.2.0",
"@graphql-codegen/typescript-urql-graphcache": "^2.2.0", "@graphql-codegen/typescript-urql-graphcache": "^2.2.0",
"@graphql-codegen/urql-introspection": "^2.1.0", "@graphql-codegen/urql-introspection": "^2.1.0",
@@ -102,7 +100,7 @@
"@nuxt/typescript-build": "^2.1.0", "@nuxt/typescript-build": "^2.1.0",
"@nuxtjs/color-mode": "^2.1.1", "@nuxtjs/color-mode": "^2.1.1",
"@nuxtjs/dotenv": "^1.4.1", "@nuxtjs/dotenv": "^1.4.1",
"@nuxtjs/eslint-config-typescript": "^6.0.1", "@nuxtjs/eslint-config-typescript": "^7.0.2",
"@nuxtjs/eslint-module": "^3.0.2", "@nuxtjs/eslint-module": "^3.0.2",
"@nuxtjs/google-analytics": "^2.4.0", "@nuxtjs/google-analytics": "^2.4.0",
"@nuxtjs/google-fonts": "^1.3.0", "@nuxtjs/google-fonts": "^1.3.0",
@@ -120,11 +118,11 @@
"@vue/test-utils": "^1.2.2", "@vue/test-utils": "^1.2.2",
"babel-core": "^7.0.0-bridge.0", "babel-core": "^7.0.0-bridge.0",
"babel-jest": "^27.3.1", "babel-jest": "^27.3.1",
"eslint": "^7.32.0", "eslint": "^8.1.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-nuxt": "^2.0.0", "eslint-plugin-nuxt": "^3.0.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^7.20.0", "eslint-plugin-vue": "^8.0.3",
"jest": "^27.3.1", "jest": "^27.3.1",
"jest-serializer-vue": "^2.0.2", "jest-serializer-vue": "^2.0.2",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
@@ -134,9 +132,10 @@
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"sass": "^1.43.4", "sass": "^1.43.4",
"sass-loader": "^10.2.0", "sass-loader": "^10.2.0",
"stylelint": "^13.13.1", "stylelint": "^14.0.1",
"stylelint-config-prettier": "^9.0.3", "stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^22.0.0", "stylelint-config-standard": "^23.0.0",
"stylelint-config-standard-scss": "^2.0.1",
"ts-jest": "^27.0.7", "ts-jest": "^27.0.7",
"typescript": "^4.4.4", "typescript": "^4.4.4",
"unplugin-vue2-script-setup": "^0.6.13", "unplugin-vue2-script-setup": "^0.6.13",

View File

@@ -25,5 +25,6 @@ module.exports = {
"import/no-named-as-default": "off", "import/no-named-as-default": "off",
"no-undef": "off", "no-undef": "off",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
}, },
} }

View File

@@ -2,5 +2,5 @@ export default {
preset: "ts-jest", preset: "ts-jest",
testEnvironment: "node", testEnvironment: "node",
collectCoverage: true, collectCoverage: true,
setupFilesAfterEnv: ['./jest.setup.ts'], setupFilesAfterEnv: ["./jest.setup.ts"],
} }

View File

@@ -1 +1 @@
require('@relmify/jest-fp-ts'); require("@relmify/jest-fp-ts")

View File

@@ -11,8 +11,8 @@
}, },
"scripts": { "scripts": {
"demo": "esrun src/demo.ts", "demo": "esrun src/demo.ts",
"lint": "eslint --ext .ts,.js --ignore-path .gitignore", "lint": "eslint --ext .ts,.js --ignore-path .gitignore .",
"lintfix": "eslint --ext .ts,.js --ignore-path .gitignore --fix", "lintfix": "eslint --fix --ext .ts,.js --ignore-path .gitignore .",
"test": "npx jest", "test": "npx jest",
"build": "npx tsc", "build": "npx tsc",
"clean": "npx tsc --build --clean", "clean": "npx tsc --build --clean",
@@ -43,9 +43,9 @@
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"@types/lodash": "^4.14.176", "@types/lodash": "^4.14.176",
"@types/node": "^16.11.5", "@types/node": "^16.11.5",
"@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^4.33.0", "@typescript-eslint/parser": "^5.3.0",
"eslint": "^7.32.0", "eslint": "^8.1.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"io-ts": "^2.2.16", "io-ts": "^2.2.16",
@@ -54,10 +54,5 @@
"pretty-quick": "^3.1.1", "pretty-quick": "^3.1.1",
"ts-jest": "^27.0.7", "ts-jest": "^27.0.7",
"typescript": "^4.4.4" "typescript": "^4.4.4"
},
"jest": {
"setupFilesAfterEnv": [
"@relmify/jest-fp-ts"
]
} }
} }

View File

@@ -8,11 +8,14 @@ describe("execPreRequestScript", () => {
` `
pw.env.set("bob", "newbob") pw.env.set("bob", "newbob")
`, `,
[{ key: "bob", value: "oldbob" }, { key: "foo", value: "bar" }] [
{ key: "bob", value: "oldbob" },
{ key: "foo", value: "bar" },
]
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
{ key: "bob", value: "newbob" }, { key: "bob", value: "newbob" },
{ key: "foo", value: "bar" } { key: "foo", value: "bar" },
]) ])
}) })
@@ -22,7 +25,10 @@ describe("execPreRequestScript", () => {
` `
pw.env.set(10, "newbob") pw.env.set(10, "newbob")
`, `,
[{ key: "bob", value: "oldbob" }, { key: "foo", value: "bar" }] [
{ key: "bob", value: "oldbob" },
{ key: "foo", value: "bar" },
]
)() )()
).resolves.toBeLeft() ).resolves.toBeLeft()
}) })
@@ -33,7 +39,10 @@ describe("execPreRequestScript", () => {
` `
pw.env.set("bob", 10) pw.env.set("bob", 10)
`, `,
[{ key: "bob", value: "oldbob" }, { key: "foo", value: "bar" }] [
{ key: "bob", value: "oldbob" },
{ key: "foo", value: "bar" },
]
)() )()
).resolves.toBeLeft() ).resolves.toBeLeft()
}) })
@@ -44,7 +53,10 @@ describe("execPreRequestScript", () => {
` `
pw.env.set("bob", pw.env.set("bob",
`, `,
[{ key: "bob", value: "oldbob" }, { key: "foo", value: "bar" }] [
{ key: "bob", value: "oldbob" },
{ key: "foo", value: "bar" },
]
)() )()
).resolves.toBeLeft() ).resolves.toBeLeft()
}) })
@@ -57,8 +69,6 @@ describe("execPreRequestScript", () => {
`, `,
[] []
)() )()
).resolves.toEqualRight( ).resolves.toEqualRight([{ key: "foo", value: "bar" }])
[{ key: "foo", value: "bar" }]
)
}) })
}) })

View File

@@ -4,7 +4,7 @@ import "@relmify/jest-fp-ts"
const fakeResponse: TestResponse = { const fakeResponse: TestResponse = {
status: 200, status: 200,
body: "hoi", body: "hoi",
headers: [] headers: [],
} }
describe("toBe", () => { describe("toBe", () => {
@@ -19,7 +19,9 @@ describe("toBe", () => {
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ status: "pass", message: "Expected '2' to be '2'" }], expectResults: [
{ status: "pass", message: "Expected '2' to be '2'" },
],
}), }),
]) ])
}) })
@@ -34,7 +36,9 @@ describe("toBe", () => {
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ status: "fail", message: "Expected '2' to be '4'" }], expectResults: [
{ status: "fail", message: "Expected '2' to be '4'" },
],
}), }),
]) ])
}) })
@@ -51,10 +55,12 @@ describe("toBe", () => {
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: "Expected '2' to not be '2'", status: "fail",
}], message: "Expected '2' to not be '2'",
},
],
}), }),
]) ])
}) })
@@ -69,10 +75,12 @@ describe("toBe", () => {
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: "Expected '2' to not be '4'", status: "pass",
}], message: "Expected '2' to not be '4'",
},
],
}), }),
]) ])
}) })
@@ -85,14 +93,16 @@ test("strict checks types", () => {
` `
pw.expect(2).toBe("2") pw.expect(2).toBe("2")
`, `,
fakeResponse fakeResponse
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: "Expected '2' to be '2'", status: "fail",
}], message: "Expected '2' to be '2'",
},
],
}), }),
]) ])
}) })

View File

@@ -4,7 +4,7 @@ import "@relmify/jest-fp-ts"
const fakeResponse: TestResponse = { const fakeResponse: TestResponse = {
status: 200, status: 200,
body: "hoi", body: "hoi",
headers: [] headers: [],
} }
describe("toBeLevel2xx", () => { describe("toBeLevel2xx", () => {
@@ -14,10 +14,12 @@ describe("toBeLevel2xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to be 200-level status`, status: "pass",
}], message: `Expected '${i}' to be 200-level status`,
},
],
}), }),
]) ])
} }
@@ -29,10 +31,12 @@ describe("toBeLevel2xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to be 200-level status`, status: "fail",
}], message: `Expected '${i}' to be 200-level status`,
},
],
}), }),
]) ])
} }
@@ -43,11 +47,14 @@ describe("toBeLevel2xx", () => {
execTestScript(`pw.expect("foo").toBeLevel2xx()`, fakeResponse)() execTestScript(`pw.expect("foo").toBeLevel2xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 200-level status but could not parse value 'foo'", status: "error",
}], message:
}) "Expected 200-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
@@ -57,10 +64,12 @@ describe("toBeLevel2xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to not be 200-level status`, status: "fail",
}], message: `Expected '${i}' to not be 200-level status`,
},
],
}), }),
]) ])
} }
@@ -72,10 +81,12 @@ describe("toBeLevel2xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to not be 200-level status`, status: "pass",
}], message: `Expected '${i}' to not be 200-level status`,
},
],
}), }),
]) ])
} }
@@ -86,11 +97,14 @@ describe("toBeLevel2xx", () => {
execTestScript(`pw.expect("foo").not.toBeLevel2xx()`, fakeResponse)() execTestScript(`pw.expect("foo").not.toBeLevel2xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 200-level status but could not parse value 'foo'", status: "error",
}], message:
}) "Expected 200-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
}) })
@@ -102,10 +116,12 @@ describe("toBeLevel3xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to be 300-level status`, status: "pass",
}], message: `Expected '${i}' to be 300-level status`,
},
],
}), }),
]) ])
} }
@@ -117,10 +133,12 @@ describe("toBeLevel3xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to be 300-level status`, status: "fail",
}], message: `Expected '${i}' to be 300-level status`,
},
],
}), }),
]) ])
} }
@@ -131,11 +149,14 @@ describe("toBeLevel3xx", () => {
execTestScript(`pw.expect("foo").toBeLevel3xx()`, fakeResponse)() execTestScript(`pw.expect("foo").toBeLevel3xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 300-level status but could not parse value 'foo'", status: "error",
}], message:
}) "Expected 300-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
@@ -145,10 +166,12 @@ describe("toBeLevel3xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to not be 300-level status`, status: "fail",
}], message: `Expected '${i}' to not be 300-level status`,
},
],
}), }),
]) ])
} }
@@ -160,10 +183,12 @@ describe("toBeLevel3xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to not be 300-level status`, status: "pass",
}], message: `Expected '${i}' to not be 300-level status`,
},
],
}), }),
]) ])
} }
@@ -174,14 +199,16 @@ describe("toBeLevel3xx", () => {
execTestScript(`pw.expect("foo").not.toBeLevel3xx()`, fakeResponse)() execTestScript(`pw.expect("foo").not.toBeLevel3xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 300-level status but could not parse value 'foo'", status: "error",
}] message:
}) "Expected 300-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
}) })
describe("toBeLevel4xx", () => { describe("toBeLevel4xx", () => {
@@ -191,10 +218,12 @@ describe("toBeLevel4xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to be 400-level status`, status: "pass",
}], message: `Expected '${i}' to be 400-level status`,
},
],
}), }),
]) ])
} }
@@ -206,10 +235,12 @@ describe("toBeLevel4xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to be 400-level status`, status: "fail",
}], message: `Expected '${i}' to be 400-level status`,
},
],
}), }),
]) ])
} }
@@ -220,11 +251,14 @@ describe("toBeLevel4xx", () => {
execTestScript(`pw.expect("foo").toBeLevel4xx()`, fakeResponse)() execTestScript(`pw.expect("foo").toBeLevel4xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 400-level status but could not parse value 'foo'", status: "error",
}], message:
}) "Expected 400-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
@@ -234,10 +268,12 @@ describe("toBeLevel4xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to not be 400-level status`, status: "fail",
}], message: `Expected '${i}' to not be 400-level status`,
},
],
}), }),
]) ])
} }
@@ -249,10 +285,12 @@ describe("toBeLevel4xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to not be 400-level status`, status: "pass",
}], message: `Expected '${i}' to not be 400-level status`,
},
],
}), }),
]) ])
} }
@@ -263,11 +301,14 @@ describe("toBeLevel4xx", () => {
execTestScript(`pw.expect("foo").not.toBeLevel4xx()`, fakeResponse)() execTestScript(`pw.expect("foo").not.toBeLevel4xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 400-level status but could not parse value 'foo'", status: "error",
}], message:
}) "Expected 400-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
}) })
@@ -279,10 +320,12 @@ describe("toBeLevel5xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to be 500-level status`, status: "pass",
}], message: `Expected '${i}' to be 500-level status`,
},
],
}), }),
]) ])
} }
@@ -294,10 +337,12 @@ describe("toBeLevel5xx", () => {
execTestScript(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to be 500-level status`, status: "fail",
}], message: `Expected '${i}' to be 500-level status`,
},
],
}), }),
]) ])
} }
@@ -308,11 +353,14 @@ describe("toBeLevel5xx", () => {
execTestScript(`pw.expect("foo").toBeLevel5xx()`, fakeResponse)() execTestScript(`pw.expect("foo").toBeLevel5xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 500-level status but could not parse value 'foo'", status: "error",
}], message:
}) "Expected 500-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
@@ -322,10 +370,12 @@ describe("toBeLevel5xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "fail", {
message: `Expected '${i}' to not be 500-level status`, status: "fail",
}], message: `Expected '${i}' to not be 500-level status`,
},
],
}), }),
]) ])
} }
@@ -337,10 +387,12 @@ describe("toBeLevel5xx", () => {
execTestScript(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)() execTestScript(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "pass", {
message: `Expected '${i}' to not be 500-level status`, status: "pass",
}], message: `Expected '${i}' to not be 500-level status`,
},
],
}), }),
]) ])
} }
@@ -351,11 +403,14 @@ describe("toBeLevel5xx", () => {
execTestScript(`pw.expect("foo").not.toBeLevel5xx()`, fakeResponse)() execTestScript(`pw.expect("foo").not.toBeLevel5xx()`, fakeResponse)()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [{ expectResults: [
status: "error", {
message: "Expected 500-level status but could not parse value 'foo'", status: "error",
}], message:
}) "Expected 500-level status but could not parse value 'foo'",
},
],
}),
]) ])
}) })
}) })

View File

@@ -3,7 +3,7 @@ import { execTestScript, TestResponse } from "../../../test-runner"
const fakeResponse: TestResponse = { const fakeResponse: TestResponse = {
status: 200, status: 200,
body: "hoi", body: "hoi",
headers: [] headers: [],
} }
describe("toBeType", () => { describe("toBeType", () => {
@@ -16,16 +16,23 @@ describe("toBeType", () => {
pw.expect(true).toBeType("boolean") pw.expect(true).toBeType("boolean")
pw.expect({}).toBeType("object") pw.expect({}).toBeType("object")
pw.expect(undefined).toBeType("undefined") pw.expect(undefined).toBeType("undefined")
`, fakeResponse `,
fakeResponse
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "pass", message: `Expected '2' to be type 'number'` }, { status: "pass", message: `Expected '2' to be type 'number'` },
{ status: "pass", message: `Expected '2' to be type 'string'` }, { status: "pass", message: `Expected '2' to be type 'string'` },
{ status: "pass", message: `Expected 'true' to be type 'boolean'` }, { status: "pass", message: `Expected 'true' to be type 'boolean'` },
{ status: "pass", message: `Expected '[object Object]' to be type 'object'` }, {
{ status: "pass", message: `Expected 'undefined' to be type 'undefined'` }, status: "pass",
message: `Expected '[object Object]' to be type 'object'`,
},
{
status: "pass",
message: `Expected 'undefined' to be type 'undefined'`,
},
], ],
}), }),
]) ])
@@ -46,11 +53,17 @@ describe("toBeType", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "fail", message: `Expected '2' to be type 'string'`}, { status: "fail", message: `Expected '2' to be type 'string'` },
{ status: "fail", message: `Expected '2' to be type 'number'`}, { status: "fail", message: `Expected '2' to be type 'number'` },
{ status: "fail", message: `Expected 'true' to be type 'string'`}, { status: "fail", message: `Expected 'true' to be type 'string'` },
{ status: "fail", message: `Expected '[object Object]' to be type 'number'`}, {
{ status: "fail", message: `Expected 'undefined' to be type 'number'`}, status: "fail",
message: `Expected '[object Object]' to be type 'number'`,
},
{
status: "fail",
message: `Expected 'undefined' to be type 'number'`,
},
], ],
}), }),
]) ])
@@ -65,16 +78,26 @@ describe("toBeType", () => {
pw.expect(true).not.toBeType("boolean") pw.expect(true).not.toBeType("boolean")
pw.expect({}).not.toBeType("object") pw.expect({}).not.toBeType("object")
pw.expect(undefined).not.toBeType("undefined") pw.expect(undefined).not.toBeType("undefined")
`, fakeResponse `,
fakeResponse
)() )()
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "fail", message: `Expected '2' to not be type 'number'` }, { status: "fail", message: `Expected '2' to not be type 'number'` },
{ status: "fail", message: `Expected '2' to not be type 'string'` }, { status: "fail", message: `Expected '2' to not be type 'string'` },
{ status: "fail", message: `Expected 'true' to not be type 'boolean'` }, {
{ status: "fail", message: `Expected '[object Object]' to not be type 'object'` }, status: "fail",
{ status: "fail", message: `Expected 'undefined' to not be type 'undefined'` }, message: `Expected 'true' to not be type 'boolean'`,
},
{
status: "fail",
message: `Expected '[object Object]' to not be type 'object'`,
},
{
status: "fail",
message: `Expected 'undefined' to not be type 'undefined'`,
},
], ],
}), }),
]) ])
@@ -97,9 +120,18 @@ describe("toBeType", () => {
expectResults: [ expectResults: [
{ status: "pass", message: `Expected '2' to not be type 'string'` }, { status: "pass", message: `Expected '2' to not be type 'string'` },
{ status: "pass", message: `Expected '2' to not be type 'number'` }, { status: "pass", message: `Expected '2' to not be type 'number'` },
{ status: "pass", message: `Expected 'true' to not be type 'string'` }, {
{ status: "pass", message: `Expected '[object Object]' to not be type 'number'` }, status: "pass",
{ status: "pass", message: `Expected 'undefined' to not be type 'number'` }, message: `Expected 'true' to not be type 'string'`,
},
{
status: "pass",
message: `Expected '[object Object]' to not be type 'number'`,
},
{
status: "pass",
message: `Expected 'undefined' to not be type 'number'`,
},
], ],
}), }),
]) ])
@@ -120,13 +152,28 @@ describe("toBeType", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, {
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, status: "error",
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, },
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, {
] status: "error",
}) message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
{
status: "error",
message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
{
status: "error",
message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
{
status: "error",
message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
],
}),
]) ])
}) })
@@ -145,13 +192,28 @@ describe("toBeType", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, {
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, status: "error",
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, },
{ status: "error", message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` }, {
] status: "error",
}) message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
{
status: "error",
message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
{
status: "error",
message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
{
status: "error",
message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
},
],
}),
]) ])
}) })
}) })

View File

@@ -3,7 +3,7 @@ import { execTestScript, TestResponse } from "../../../test-runner"
const fakeResponse: TestResponse = { const fakeResponse: TestResponse = {
status: 200, status: 200,
body: "hoi", body: "hoi",
headers: [] headers: [],
} }
describe("toHaveLength", () => { describe("toHaveLength", () => {
@@ -20,7 +20,7 @@ describe("toHaveLength", () => {
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "pass", message: "Expected the array to be of length '4'" }, { status: "pass", message: "Expected the array to be of length '4'" },
{ status: "pass", message: "Expected the array to be of length '0'" }, { status: "pass", message: "Expected the array to be of length '0'" },
], ],
}), }),
]) ])
@@ -57,8 +57,14 @@ describe("toHaveLength", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "fail", message: "Expected the array to not be of length '4'" }, {
{ status: "fail", message: "Expected the array to not be of length '0'" }, status: "fail",
message: "Expected the array to not be of length '4'",
},
{
status: "fail",
message: "Expected the array to not be of length '0'",
},
], ],
}), }),
]) ])
@@ -76,8 +82,14 @@ describe("toHaveLength", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "pass", message: "Expected the array to not be of length '4'" }, {
{ status: "pass", message: "Expected the array to not be of length '0'" }, status: "pass",
message: "Expected the array to not be of length '4'",
},
{
status: "pass",
message: "Expected the array to not be of length '0'",
},
], ],
}), }),
]) ])
@@ -95,10 +107,18 @@ describe("toHaveLength", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "error", message: "Expected toHaveLength to be called for an array or string" }, {
{ status: "error", message: "Expected toHaveLength to be called for an array or string" }, status: "error",
] message:
}) "Expected toHaveLength to be called for an array or string",
},
{
status: "error",
message:
"Expected toHaveLength to be called for an array or string",
},
],
}),
]) ])
}) })
@@ -114,10 +134,18 @@ describe("toHaveLength", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "error", message: "Expected toHaveLength to be called for an array or string" }, {
{ status: "error", message: "Expected toHaveLength to be called for an array or string" }, status: "error",
] message:
}) "Expected toHaveLength to be called for an array or string",
},
{
status: "error",
message:
"Expected toHaveLength to be called for an array or string",
},
],
}),
]) ])
}) })
@@ -132,9 +160,12 @@ describe("toHaveLength", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "error", message: "Argument for toHaveLength should be a number" }, {
status: "error",
message: "Argument for toHaveLength should be a number",
},
], ],
}) }),
]) ])
}) })
@@ -149,9 +180,12 @@ describe("toHaveLength", () => {
).resolves.toEqualRight([ ).resolves.toEqualRight([
expect.objectContaining({ expect.objectContaining({
expectResults: [ expectResults: [
{ status: "error", message: "Argument for toHaveLength should be a number" }, {
status: "error",
message: "Argument for toHaveLength should be a number",
},
], ],
}) }),
]) ])
}) })
}) })

View File

@@ -3,7 +3,7 @@ import { execTestScript, TestResponse } from "../../test-runner"
const fakeResponse: TestResponse = { const fakeResponse: TestResponse = {
status: 200, status: 200,
body: "hoi", body: "hoi",
headers: [] headers: [],
} }
describe("execTestScript function behavior", () => { describe("execTestScript function behavior", () => {
@@ -21,7 +21,7 @@ describe("execTestScript function behavior", () => {
`, `,
fakeResponse fakeResponse
)() )()
).resolves.toBeRight(); ).resolves.toBeRight()
}) })
test("resolves for tests with failed expectations", () => { test("resolves for tests with failed expectations", () => {
@@ -35,7 +35,8 @@ describe("execTestScript function behavior", () => {
pw.expect(size * 4).toBe(4000); pw.expect(size * 4).toBe(4000);
pw.expect(size / 4).not.toBe(250); pw.expect(size / 4).not.toBe(250);
}); });
`, fakeResponse `,
fakeResponse
)() )()
).resolves.toBeRight() ).resolves.toBeRight()
}) })
@@ -52,7 +53,8 @@ describe("execTestScript function behavior", () => {
pw.expect(size * 4).toBe(4000); pw.expect(size * 4).toBe(4000);
pw.expect(size / 4).not.toBe(250); pw.expect(size / 4).not.toBe(250);
}); });
`, fakeResponse `,
fakeResponse
)() )()
).resolves.toBeLeft() ).resolves.toBeLeft()
}) })

View File

@@ -15,16 +15,15 @@ afterAll(() => {
}) })
describe("marshalObjectToVM", () => { describe("marshalObjectToVM", () => {
test("successfully marshals simple object into the vm", () => { test("successfully marshals simple object into the vm", () => {
const testObj = { const testObj = {
a: 1 a: 1,
} }
const objVMHandle: QuickJS.QuickJSHandle | null = pipe( const objVMHandle: QuickJS.QuickJSHandle | null = pipe(
marshalObjectToVM(vm, testObj), marshalObjectToVM(vm, testObj),
match( match(
(e) => null, () => null,
(result) => result (result) => result
) )
) )
@@ -38,7 +37,7 @@ describe("marshalObjectToVM", () => {
test("fails marshalling cyclic object into vm", () => { test("fails marshalling cyclic object into vm", () => {
const testObj = { const testObj = {
a: 1, a: 1,
b: null as any b: null as any,
} }
testObj.b = testObj testObj.b = testObj
@@ -46,12 +45,11 @@ describe("marshalObjectToVM", () => {
const objVMHandle: QuickJS.QuickJSHandle | null = pipe( const objVMHandle: QuickJS.QuickJSHandle | null = pipe(
marshalObjectToVM(vm, testObj), marshalObjectToVM(vm, testObj),
match( match(
(e) => null, () => null,
(result) => result (result) => result
) )
) )
expect(objVMHandle).toBeNull() expect(objVMHandle).toBeNull()
}) })
})
})

View File

@@ -1,15 +1,13 @@
import { runTestScript } from "./index" import { runTestScript } from "./index"
import { TestResponse } from "./test-runner" import { TestResponse } from "./test-runner"
const dummyResponse: TestResponse = { const dummyResponse: TestResponse = {
status: 200, status: 200,
body: "hoi", body: "hoi",
headers: [] headers: [],
}; }
// eslint-disable-next-line prettier/prettier // eslint-disable-next-line prettier/prettier
(async () => { ;(async () => {
console.dir( console.dir(
await runTestScript( await runTestScript(
` `
@@ -46,7 +44,7 @@ const dummyResponse: TestResponse = {
pw.expect(arr).not.toHaveLength(4); pw.expect(arr).not.toHaveLength(4);
}); });
`, `,
dummyResponse dummyResponse
), ),
{ {
depth: 100, depth: 100,

View File

@@ -1 +1 @@
import '@relmify/jest-fp-ts'; import "@relmify/jest-fp-ts"

View File

@@ -1,7 +1,11 @@
import { pipe } from "fp-ts/lib/function" import { pipe } from "fp-ts/lib/function"
import { chain, right } from "fp-ts/lib/TaskEither" import { chain, right } from "fp-ts/lib/TaskEither"
import { execPreRequestScript } from "./preRequest" import { execPreRequestScript } from "./preRequest"
import { execTestScript, TestResponse, TestDescriptor as _TestDescriptor } from "./test-runner" import {
execTestScript,
TestResponse,
TestDescriptor as _TestDescriptor,
} from "./test-runner"
export type TestDescriptor = _TestDescriptor export type TestDescriptor = _TestDescriptor
/** /**
@@ -9,13 +13,11 @@ export type TestDescriptor = _TestDescriptor
* @param testScript The string of the script to run * @param testScript The string of the script to run
* @returns A TaskEither with an error message or a TestDescriptor with the final status * @returns A TaskEither with an error message or a TestDescriptor with the final status
*/ */
export const runTestScript = ( export const runTestScript = (testScript: string, response: TestResponse) =>
testScript: string, pipe(
response: TestResponse execTestScript(testScript, response),
) => pipe( chain((results) => right(results[0])) // execTestScript returns an array of descriptors with a single element (extract that)
execTestScript(testScript, response), )
chain((results) => right(results[0])) // execTestScript returns an array of descriptors with a single element (extract that)
)
/** /**
* Executes a given pre-request script on the sandbox * Executes a given pre-request script on the sandbox
@@ -23,4 +25,4 @@ export const runTestScript = (
* @param env The envirionment variables active * @param env The envirionment variables active
* @returns A TaskEither with an error message or an array of the final environments with the all the script values applied * @returns A TaskEither with an error message or an array of the final environments with the all the script values applied
*/ */
export const runPreRequestScript = execPreRequestScript export const runPreRequestScript = execPreRequestScript

View File

@@ -1,23 +1,23 @@
import { pipe } from "fp-ts/lib/function"; import { pipe } from "fp-ts/lib/function"
import { chain, TaskEither, tryCatch, right, left } from "fp-ts/lib/TaskEither"; import { chain, TaskEither, tryCatch, right, left } from "fp-ts/lib/TaskEither"
import * as qjs from "quickjs-emscripten"; import * as qjs from "quickjs-emscripten"
import clone from "lodash/clone"; import clone from "lodash/clone"
type EnvEntry = { type EnvEntry = {
key: string; key: string
value: string; value: string
}; }
export const execPreRequestScript = ( export const execPreRequestScript = (
preRequestScript: string, preRequestScript: string,
env: EnvEntry[] env: EnvEntry[]
): TaskEither<string, EnvEntry[]> => pipe( ): TaskEither<string, EnvEntry[]> =>
tryCatch( pipe(
async () => await qjs.getQuickJS(), tryCatch(
(reason) => `QuickJS initialization failed: ${reason}` async () => await qjs.getQuickJS(),
), (reason) => `QuickJS initialization failed: ${reason}`
chain( ),
(QuickJS) => { chain((QuickJS) => {
const finalEnv = clone(env) const finalEnv = clone(env)
const vm = QuickJS.createVm() const vm = QuickJS.createVm()
@@ -26,30 +26,35 @@ export const execPreRequestScript = (
const envHandle = vm.newObject() const envHandle = vm.newObject()
const envSetFuncHandle = vm.newFunction("set", (keyHandle, valueHandle) => { const envSetFuncHandle = vm.newFunction(
const key = vm.dump(keyHandle) "set",
const value = vm.dump(valueHandle) (keyHandle, valueHandle) => {
const key = vm.dump(keyHandle)
const value = vm.dump(valueHandle)
if (typeof key !== "string") return { if (typeof key !== "string")
error: vm.newString("Expected key to be a string") return {
error: vm.newString("Expected key to be a string"),
}
if (typeof value !== "string")
return {
error: vm.newString("Expected value to be a string"),
}
const keyIndex = finalEnv.findIndex((env) => env.key === key)
if (keyIndex === -1) {
finalEnv.push({ key, value })
} else {
finalEnv[keyIndex] = { key, value }
}
return {
value: vm.undefined,
}
} }
)
if (typeof value !== "string") return {
error: vm.newString("Expected value to be a string")
}
const keyIndex = finalEnv.findIndex((env) => env.key === key)
if (keyIndex === -1) {
finalEnv.push({ key, value })
} else {
finalEnv[keyIndex] = { key, value }
}
return {
value: vm.undefined
}
})
vm.setProp(envHandle, "set", envSetFuncHandle) vm.setProp(envHandle, "set", envSetFuncHandle)
envSetFuncHandle.dispose() envSetFuncHandle.dispose()
@@ -72,6 +77,5 @@ export const execPreRequestScript = (
vm.dispose() vm.dispose()
return right(finalEnv) return right(finalEnv)
} })
) )
)

View File

@@ -9,9 +9,9 @@ import { marshalObjectToVM } from "./utils"
*/ */
export type TestResponse = { export type TestResponse = {
/** Status Code of the response */ /** Status Code of the response */
status: number, status: number
/** List of headers returned */ /** List of headers returned */
headers: { key: string, value: string }[], headers: { key: string; value: string }[]
/** /**
* Body of the response, this will be the JSON object if it is a JSON content type, else body string * Body of the response, this will be the JSON object if it is a JSON content type, else body string
*/ */
@@ -21,8 +21,7 @@ export type TestResponse = {
/** /**
* The result of an expectation statement * The result of an expectation statement
*/ */
type ExpectResult = type ExpectResult = { status: "pass" | "fail" | "error"; message: string } // The expectation failed (fail) or errored (error)
| { status: "pass" | "fail" | "error", message: string } // The expectation failed (fail) or errored (error)
/** /**
* An object defining the result of the execution of a * An object defining the result of the execution of a
@@ -68,14 +67,18 @@ function createExpectation(
if (negated) assertion = !assertion if (negated) assertion = !assertion
if (assertion) { if (assertion) {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "pass", status: "pass",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be '${expectedVal}'` message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be '${expectedVal}'`,
}) })
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "fail", status: "fail",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be '${expectedVal}'`, message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be '${expectedVal}'`,
}) })
} }
@@ -91,13 +94,16 @@ function createExpectation(
if (assertion) { if (assertion) {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "pass", status: "pass",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be 200-level status`, message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be 200-level status`,
}) })
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "fail", status: "fail",
message: message: `Expected '${expectVal}' to${
`Expected '${expectVal}' to${negated ? " not" : ""} be 200-level status`, negated ? " not" : ""
} be 200-level status`,
}) })
} }
} else { } else {
@@ -119,13 +125,16 @@ function createExpectation(
if (assertion) { if (assertion) {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "pass", status: "pass",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be 300-level status`, message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be 300-level status`,
}) })
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "fail", status: "fail",
message: message: `Expected '${expectVal}' to${
`Expected '${expectVal}' to${negated ? " not" : ""} be 300-level status`, negated ? " not" : ""
} be 300-level status`,
}) })
} }
} else { } else {
@@ -147,13 +156,16 @@ function createExpectation(
if (assertion) { if (assertion) {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "pass", status: "pass",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be 400-level status`, message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be 400-level status`,
}) })
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "fail", status: "fail",
message: message: `Expected '${expectVal}' to${
`Expected '${expectVal}' to${negated ? " not" : ""} be 400-level status`, negated ? " not" : ""
} be 400-level status`,
}) })
} }
} else { } else {
@@ -175,12 +187,16 @@ function createExpectation(
if (assertion) { if (assertion) {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "pass", status: "pass",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be 500-level status`, message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be 500-level status`,
}) })
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "fail", status: "fail",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be 500-level status` message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be 500-level status`,
}) })
} }
} else { } else {
@@ -189,7 +205,7 @@ function createExpectation(
message: `Expected 500-level status but could not parse value '${expectVal}'`, message: `Expected 500-level status but could not parse value '${expectVal}'`,
}) })
} }
return { value: vm.undefined } return { value: vm.undefined }
}) })
@@ -197,25 +213,40 @@ function createExpectation(
const expectedType = vm.dump(expectedValHandle) const expectedType = vm.dump(expectedValHandle)
// Check if the expectation param is a valid type name string, else error // Check if the expectation param is a valid type name string, else error
if (["string", "boolean", "number", "object", "undefined", "bigint", "symbol", "function"].includes(expectedType)) { if (
[
"string",
"boolean",
"number",
"object",
"undefined",
"bigint",
"symbol",
"function",
].includes(expectedType)
) {
let assertion = typeof expectVal === expectedType let assertion = typeof expectVal === expectedType
if (negated) assertion = !assertion if (negated) assertion = !assertion
if (assertion) { if (assertion) {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "pass", status: "pass",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be type '${expectedType}'` message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be type '${expectedType}'`,
}) })
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "fail", status: "fail",
message: `Expected '${expectVal}' to${negated ? " not" : ""} be type '${expectedType}'`, message: `Expected '${expectVal}' to${
negated ? " not" : ""
} be type '${expectedType}'`,
}) })
} }
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "error", status: "error",
message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"` message: `Argument for toBeType should be "string", "boolean", "number", "object", "undefined", "bigint", "symbol" or "function"`,
}) })
} }
@@ -240,25 +271,29 @@ function createExpectation(
if (typeof expectedLength === "number" && !Number.isNaN(expectedLength)) { if (typeof expectedLength === "number" && !Number.isNaN(expectedLength)) {
let assertion = (expectVal as any[]).length === expectedLength let assertion = (expectVal as any[]).length === expectedLength
if (negated) assertion = !assertion if (negated) assertion = !assertion
if (assertion) { if (assertion) {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "pass", status: "pass",
message: `Expected the array to${negated ? " not" : ""} be of length '${expectedLength}'`, message: `Expected the array to${
negated ? " not" : ""
} be of length '${expectedLength}'`,
}) })
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "fail", status: "fail",
message: `Expected the array to${negated ? " not" : ""} be of length '${expectedLength}'` message: `Expected the array to${
negated ? " not" : ""
} be of length '${expectedLength}'`,
}) })
} }
} else { } else {
currTestStack[currTestStack.length - 1].expectResults.push({ currTestStack[currTestStack.length - 1].expectResults.push({
status: "error", status: "error",
message: `Argument for toHaveLength should be a number` message: `Argument for toHaveLength should be a number`,
}) })
} }
return { value: vm.undefined } return { value: vm.undefined }
} }
) )
@@ -291,77 +326,81 @@ function createExpectation(
export const execTestScript = ( export const execTestScript = (
testScript: string, testScript: string,
response: TestResponse response: TestResponse
): TaskEither<string, TestDescriptor[]> => pipe( ): TaskEither<string, TestDescriptor[]> =>
tryCatch( pipe(
async () => await qjs.getQuickJS(), tryCatch(
(reason) => `QuickJS initialization failed: ${reason}` async () => await qjs.getQuickJS(),
), (reason) => `QuickJS initialization failed: ${reason}`
chain( ),
// TODO: Make this more functional ? chain(
(QuickJS) => { // TODO: Make this more functional ?
const vm = QuickJS.createVm() (QuickJS) => {
const vm = QuickJS.createVm()
const pwHandle = vm.newObject() const pwHandle = vm.newObject()
const testRunStack: TestDescriptor[] = [ const testRunStack: TestDescriptor[] = [
{ descriptor: "root", expectResults: [], children: [] }, { descriptor: "root", expectResults: [], children: [] },
] ]
const testFuncHandle = vm.newFunction( const testFuncHandle = vm.newFunction(
"test", "test",
(descriptorHandle, testFuncHandle) => { (descriptorHandle, testFuncHandle) => {
const descriptor = vm.getString(descriptorHandle) const descriptor = vm.getString(descriptorHandle)
testRunStack.push({ testRunStack.push({
descriptor, descriptor,
expectResults: [], expectResults: [],
children: [], children: [],
}) })
const result = vm.unwrapResult(vm.callFunction(testFuncHandle, vm.null)) const result = vm.unwrapResult(
result.dispose() vm.callFunction(testFuncHandle, vm.null)
)
result.dispose()
const child = testRunStack.pop() as TestDescriptor const child = testRunStack.pop() as TestDescriptor
testRunStack[testRunStack.length - 1].children.push(child) testRunStack[testRunStack.length - 1].children.push(child)
}
)
const expectFnHandle = vm.newFunction("expect", (expectValueHandle) => {
const expectVal = vm.dump(expectValueHandle)
return {
value: createExpectation(vm, expectVal, false, testRunStack),
}
})
// Marshal response object
const responseObjHandle = marshalObjectToVM(vm, response)
if (isLeft(responseObjHandle))
return left(`Response marshalling failed: ${responseObjHandle.left}`)
vm.setProp(pwHandle, "response", responseObjHandle.right)
responseObjHandle.right.dispose()
vm.setProp(pwHandle, "expect", expectFnHandle)
expectFnHandle.dispose()
vm.setProp(pwHandle, "test", testFuncHandle)
testFuncHandle.dispose()
vm.setProp(vm.global, "pw", pwHandle)
pwHandle.dispose()
const evalRes = vm.evalCode(testScript)
if (evalRes.error) {
const errorData = vm.dump(evalRes.error)
evalRes.error.dispose()
return left(`Script evaluation failed: ${errorData}`)
} }
)
const expectFnHandle = vm.newFunction("expect", (expectValueHandle) => { vm.dispose()
const expectVal = vm.dump(expectValueHandle)
return { return right(testRunStack)
value: createExpectation(vm, expectVal, false, testRunStack),
}
})
// Marshal response object
const responseObjHandle = marshalObjectToVM(vm, response)
if (isLeft(responseObjHandle)) return left(`Response marshalling failed: ${responseObjHandle.left}`)
vm.setProp(pwHandle, "response", responseObjHandle.right)
responseObjHandle.right.dispose()
vm.setProp(pwHandle, "expect", expectFnHandle)
expectFnHandle.dispose()
vm.setProp(pwHandle, "test", testFuncHandle)
testFuncHandle.dispose()
vm.setProp(vm.global, "pw", pwHandle)
pwHandle.dispose()
const evalRes = vm.evalCode(testScript)
if (evalRes.error) {
const errorData = vm.dump(evalRes.error)
evalRes.error.dispose()
return left(`Script evaluation failed: ${errorData}`)
} }
)
vm.dispose()
return right(testRunStack)
}
) )
)

View File

@@ -1,7 +1,10 @@
import { Either, left, right } from "fp-ts/lib/Either"; import { Either, left, right } from "fp-ts/lib/Either"
import * as QuickJS from "quickjs-emscripten"; import * as QuickJS from "quickjs-emscripten"
export function marshalObjectToVM(vm: QuickJS.QuickJSVm, obj: object): Either<string, QuickJS.QuickJSHandle> { export function marshalObjectToVM(
vm: QuickJS.QuickJSVm,
obj: object
): Either<string, QuickJS.QuickJSHandle> {
let jsonString let jsonString
try { try {
@@ -15,7 +18,11 @@ export function marshalObjectToVM(vm: QuickJS.QuickJSVm, obj: object): Either<st
const jsonHandle = vm.getProp(vm.global, "JSON") const jsonHandle = vm.getProp(vm.global, "JSON")
const parseFuncHandle = vm.getProp(jsonHandle, "parse") const parseFuncHandle = vm.getProp(jsonHandle, "parse")
const parseResultHandle = vm.callFunction(parseFuncHandle, vm.undefined, vmStringHandle) const parseResultHandle = vm.callFunction(
parseFuncHandle,
vm.undefined,
vmStringHandle
)
if (parseResultHandle.error) { if (parseResultHandle.error) {
parseResultHandle.error.dispose() parseResultHandle.error.dispose()
@@ -27,6 +34,6 @@ export function marshalObjectToVM(vm: QuickJS.QuickJSVm, obj: object): Either<st
vmStringHandle.dispose() vmStringHandle.dispose()
parseFuncHandle.dispose() parseFuncHandle.dispose()
jsonHandle.dispose() jsonHandle.dispose()
return right(resultHandle) return right(resultHandle)
} }

1284
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff