diff --git a/.github/workflows/release-github.yaml b/.github/workflows/release-github.yaml deleted file mode 100644 index 88b128a5..00000000 --- a/.github/workflows/release-github.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Release GitHub - -on: - push: - branches: [release/*] - -jobs: - create-github-release: - name: Create GitHub Release and Git tag - runs-on: ubuntu-latest - environment: Release - permissions: - contents: write - steps: - - uses: actions/checkout@v3 - - uses: cucumber/action-create-github-release@v1.1.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-npm.yaml b/.github/workflows/release-npm.yaml deleted file mode 100644 index d53b28c6..00000000 --- a/.github/workflows/release-npm.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: Release NPM - -on: - push: - branches: [release/*] - -jobs: - publish-npm: - name: Publish NPM module - runs-on: ubuntu-latest - environment: Release - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: '16' - cache: 'npm' - cache-dependency-path: package-lock.json - - run: npm install-test - - uses: cucumber/action-publish-npm@v1.1.0 - with: - npm-token: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index b2fc7300..04c01ba7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,2 @@ -.npm -.eslintcache -.idea/ -.aws-sam/ -packaged.yaml node_modules/ -coverage/ -.nyc_output/ -dist/ - -.aws-secrets -test-env.json -samconfig.toml \ No newline at end of file +dist/ \ No newline at end of file diff --git a/.mocharc.json b/.mocharc.json deleted file mode 100644 index ad35034b..00000000 --- a/.mocharc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": ["./features/support/env.js"], - "extension": ["ts"], - "recursive": true -} diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 137adfd9..00000000 --- a/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -.github -features -test -dist/features -dist/test diff --git a/Makefile b/Makefile deleted file mode 100644 index ac147fdf..00000000 --- a/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -ASSEMBLY_SCRIPTS = $(wildcard features/assembly-diagram-scripts/*.txt) -ASSEMBLY_SVGS = $(patsubst features/assembly-diagram-scripts/%.txt,images/%.svg,$(ASSEMBLY_SCRIPTS)) - -svgs: $(ASSEMBLY_SVGS) -.PHONY: svgs - -images/%.svg: features/assembly-diagram-scripts/%.txt - mkdir -p $(@D) - ./node_modules/.bin/assembly-diagrams $< --stroke-width 16 > $@ diff --git a/RELEASING.md b/RELEASING.md deleted file mode 100644 index 71e0bb87..00000000 --- a/RELEASING.md +++ /dev/null @@ -1 +0,0 @@ -See [.github/RELEASING](https://github.com/cucumber/.github/blob/main/RELEASING.md). diff --git a/features/assembly-diagram-scripts/dom-domain.txt b/features/assembly-diagram-scripts/dom-domain.txt deleted file mode 100644 index 458f8edb..00000000 --- a/features/assembly-diagram-scripts/dom-domain.txt +++ /dev/null @@ -1,15 +0,0 @@ -‾‾‾‾‾‾‾‾‾‾.test -StepDefinition -‾‾‾‾╲╱‾‾‾‾.test - Actor -___‾‾‾‾___.test - DomInteraction -__╱╲__╱╲__.infrastructure - DOM -‾‾╲╱‾‾╲╱‾‾.production - ReactApp -__‾‾__‾‾__.test - DomainSession -_‾_‾__‾_‾_.production - DomainLogic -__________ diff --git a/features/assembly-diagram-scripts/dom-http-domain.txt b/features/assembly-diagram-scripts/dom-http-domain.txt deleted file mode 100644 index 1ff55e81..00000000 --- a/features/assembly-diagram-scripts/dom-http-domain.txt +++ /dev/null @@ -1,19 +0,0 @@ -‾‾‾‾‾‾‾‾‾‾.test -StepDefinition -‾‾‾‾╲╱‾‾‾‾.test - Actor -___‾‾‾‾___.test - DomInteraction -__╱╲__╱╲__.infrastructure - DOM -‾‾╲╱‾‾╲╱‾‾.production - ReactApp -__‾‾__‾‾__.production - HttpSession -‾‾__‾‾__‾‾.infrastructure - Network -__‾‾__‾‾__.production - ExpressApp -_‾_‾__‾_‾_.production - DomainLogic -__________ diff --git a/features/assembly-diagram-scripts/domain.txt b/features/assembly-diagram-scripts/domain.txt deleted file mode 100644 index d0a4ea2c..00000000 --- a/features/assembly-diagram-scripts/domain.txt +++ /dev/null @@ -1,11 +0,0 @@ -‾‾‾‾‾‾‾‾‾‾.test -StepDefinition -‾‾‾‾╲╱‾‾‾‾.test - Actor -___‾‾‾‾___.test - SessionInteraction -__‾‾__‾‾__.test - DomainSession -_‾_‾__‾_‾_.production - DomainLogic -__________ diff --git a/features/assembly-diagram-scripts/http-domain.txt b/features/assembly-diagram-scripts/http-domain.txt deleted file mode 100644 index c8987cd1..00000000 --- a/features/assembly-diagram-scripts/http-domain.txt +++ /dev/null @@ -1,15 +0,0 @@ -‾‾‾‾‾‾‾‾‾‾.test -StepDefinition -‾‾‾‾╲╱‾‾‾‾.test - Actor -___‾‾‾‾___.test - SessionInteraction -__‾‾__‾‾__.production - HttpSession -‾‾__‾‾__‾‾.infrastructure - Network -__‾‾__‾‾__.production - ExpressApp -_‾_‾__‾_‾_.production - DomainLogic -__________ diff --git a/features/step_definitions/steps.ts b/features/step_definitions/steps.ts index 5a6a4ce0..d7b65202 100644 --- a/features/step_definitions/steps.ts +++ b/features/step_definitions/steps.ts @@ -1,10 +1,9 @@ import { Given, When, Then } from '@cucumber/cucumber' -import { Actor } from '../../src' +import { Actor, eventually } from '@cucumber/screenplay' import World from '../support/World' -import { Message } from '../src/types' +import { Message } from '../../src/types' import assert from 'assert' -import eventually from '../../src/eventually' import getSession from '../support/helpers/getSession' Given('{actor} is online', async function (this: World, actor: Actor) { diff --git a/features/support/World.ts b/features/support/World.ts index 89bb60d5..c09489a1 100644 --- a/features/support/World.ts +++ b/features/support/World.ts @@ -1,9 +1,9 @@ import { setWorldConstructor, Before, After, defineParameterType } from '@cucumber/cucumber' import { AppElements } from '@cucumber/electron' -import { ActorWorld, ActorParameterType } from '../../src/index' +import { ActorWorld, ActorParameterType } from '@cucumber/screenplay' -import Shouty from '../src/Shouty' -import { makeApp } from '../src/server' +import Shouty from '../../src/Shouty' +import { makeApp } from '../../src/server' import { promisify } from 'util' import { InboxMessages, Shout, StartSession } from './tasks/types' @@ -11,7 +11,7 @@ defineParameterType({ ...ActorParameterType }) defineParameterType({ name: 'coordinate', regexp: /\(\s*(\d+),\s*(\d+)\s*\)/, - transformer(x, y) { + transformer(x: string, y: string) { return { x: +x, y: +y } }, }) diff --git a/features/support/helpers/getDomUser.tsx b/features/support/helpers/getDomUser.tsx index 1e253c29..768bb0a3 100644 --- a/features/support/helpers/getDomUser.tsx +++ b/features/support/helpers/getDomUser.tsx @@ -1,8 +1,8 @@ import { createRoot } from 'react-dom/client' -import App from '../../src/components/App' +import App from '../../../src/components/App' import React from 'react' import World from '../World' -import { Actor } from '../../../src' +import { Actor } from '@cucumber/screenplay' import getSession from './getSession' import userEvent from '@testing-library/user-event' // import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup' diff --git a/features/support/helpers/getInboxMessages.ts b/features/support/helpers/getInboxMessages.ts index 6a8dd0e6..e52ba027 100644 --- a/features/support/helpers/getInboxMessages.ts +++ b/features/support/helpers/getInboxMessages.ts @@ -1,6 +1,6 @@ -import { Actor } from '../../../src' +import { Actor } from '@cucumber/screenplay' import World from '../World' -import { Message } from '../../src/types' +import { Message } from '../../../src/types' import getSession from './getSession' export default function getInboxMessages(actor: Actor): readonly Message[] { diff --git a/features/support/helpers/getSession.ts b/features/support/helpers/getSession.ts index 2b860468..7f0383de 100644 --- a/features/support/helpers/getSession.ts +++ b/features/support/helpers/getSession.ts @@ -1,7 +1,7 @@ -import { Actor } from '../../../src' +import { Actor } from '@cucumber/screenplay' import World from '../World' -import { Session } from '../../src/types' -import HttpSession from '../../src/HttpSession' +import { Session } from '../../../src/types' +import HttpSession from '../../../src/HttpSession' import NodeEventSource from 'eventsource' export default function getSession(actor: Actor): Session { diff --git a/features/support/tasks/dom/inboxMessages.ts b/features/support/tasks/dom/inboxMessages.ts index 5128b17e..19f2a337 100644 --- a/features/support/tasks/dom/inboxMessages.ts +++ b/features/support/tasks/dom/inboxMessages.ts @@ -1,4 +1,4 @@ -import { Actor } from '../../../../src' +import { Actor } from '@cucumber/screenplay' import World from '../../World' import { InboxMessages } from '../types' import { microdata, toArray } from '@cucumber/microdata' diff --git a/features/support/tasks/dom/interactions/clickShoutButton.ts b/features/support/tasks/dom/interactions/clickShoutButton.ts index 3c0a773c..f46be505 100644 --- a/features/support/tasks/dom/interactions/clickShoutButton.ts +++ b/features/support/tasks/dom/interactions/clickShoutButton.ts @@ -1,4 +1,4 @@ -import { Actor, eventually } from '../../../../../src' +import { Actor, eventually } from '@cucumber/screenplay' import World from '../../../World' import { getByText } from '@testing-library/dom' import { ClickShoutButton } from './types' diff --git a/features/support/tasks/dom/interactions/typeMessage.ts b/features/support/tasks/dom/interactions/typeMessage.ts index 19040264..c881a3a4 100644 --- a/features/support/tasks/dom/interactions/typeMessage.ts +++ b/features/support/tasks/dom/interactions/typeMessage.ts @@ -1,4 +1,4 @@ -import { Actor } from '../../../../../src' +import { Actor } from '@cucumber/screenplay' import World from '../../../World' import { getByLabelText } from '@testing-library/dom' import userEvent from '@testing-library/user-event' diff --git a/features/support/tasks/dom/interactions/types.ts b/features/support/tasks/dom/interactions/types.ts index a2a32ac5..8cfd3a4b 100644 --- a/features/support/tasks/dom/interactions/types.ts +++ b/features/support/tasks/dom/interactions/types.ts @@ -1,5 +1,5 @@ -import { Action, PromiseAction } from '../../../../../src' -import { Message } from '../../../../src/types' +import { Action, PromiseAction } from '@cucumber/screenplay' +import { Message } from '../../../../../src/types' export type ClickShoutButton = () => PromiseAction export type TypeMessage = (message: Message) => Action diff --git a/features/support/tasks/dom/shout.ts b/features/support/tasks/dom/shout.ts index 24994500..93bf2335 100644 --- a/features/support/tasks/dom/shout.ts +++ b/features/support/tasks/dom/shout.ts @@ -1,4 +1,4 @@ -import { Actor } from '../../../../src' +import { Actor } from '@cucumber/screenplay' import World from '../../World' import { Shout } from '../types' import { typeMessage } from './interactions/typeMessage' diff --git a/features/support/tasks/dom/startSession.tsx b/features/support/tasks/dom/startSession.tsx index 1507745a..20749ffe 100644 --- a/features/support/tasks/dom/startSession.tsx +++ b/features/support/tasks/dom/startSession.tsx @@ -1,4 +1,4 @@ -import { Actor, eventually } from '../../../../src' +import { Actor, eventually } from '@cucumber/screenplay' import World from '../../World' import { StartSession } from '../types' import getDomUser from '../../helpers/getDomUser' diff --git a/features/support/tasks/session/inboxMessages.ts b/features/support/tasks/session/inboxMessages.ts index 6b180103..41c8380b 100644 --- a/features/support/tasks/session/inboxMessages.ts +++ b/features/support/tasks/session/inboxMessages.ts @@ -1,4 +1,4 @@ -import { Actor } from '../../../../src' +import { Actor } from '@cucumber/screenplay' import { InboxMessages } from '../types' import World from '../../World' import getInboxMessages from '../../helpers/getInboxMessages' diff --git a/features/support/tasks/session/shout.ts b/features/support/tasks/session/shout.ts index 649f3936..c245ad63 100644 --- a/features/support/tasks/session/shout.ts +++ b/features/support/tasks/session/shout.ts @@ -1,7 +1,7 @@ -import { Actor } from '../../../../src' +import { Actor } from '@cucumber/screenplay' import World from '../../World' import { Shout } from '../types' -import { Message } from '../../../src/types' +import { Message } from '../../../../src/types' import getSession from '../../helpers/getSession' export const shout: Shout = (message: Message) => { diff --git a/features/support/tasks/session/startSession.ts b/features/support/tasks/session/startSession.ts index a85ea42e..3dbe84a9 100644 --- a/features/support/tasks/session/startSession.ts +++ b/features/support/tasks/session/startSession.ts @@ -1,4 +1,4 @@ -import { Actor } from '../../../../src' +import { Actor } from '@cucumber/screenplay' import World from '../../World' import { StartSession } from '../types' import getSession from '../../helpers/getSession' diff --git a/features/support/tasks/types.ts b/features/support/tasks/types.ts index a1c9fcff..7a4acf60 100644 --- a/features/support/tasks/types.ts +++ b/features/support/tasks/types.ts @@ -1,5 +1,5 @@ -import { Action, PromiseAction } from '../../../src' -import { Message } from '../../src/types' +import { Action, PromiseAction } from '@cucumber/screenplay' +import { Message } from '../../../src/types' export type StartSession = () => PromiseAction export type Shout = (message: Message) => PromiseAction diff --git a/images/dom-domain.svg b/images/dom-domain.svg deleted file mode 100644 index b55ed820..00000000 --- a/images/dom-domain.svg +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - StepDefinition - - - - Actor - - - - DomInteraction - - - - DOM - - - - ReactApp - - - - DomainSession - - - - DomainLogic - - diff --git a/images/dom-http-domain.svg b/images/dom-http-domain.svg deleted file mode 100644 index 220495a6..00000000 --- a/images/dom-http-domain.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - StepDefinition - - - - Actor - - - - DomInteraction - - - - DOM - - - - ReactApp - - - - HttpSession - - - - Network - - - - ExpressApp - - - - DomainLogic - - diff --git a/images/domain.svg b/images/domain.svg deleted file mode 100644 index bd4ba37f..00000000 --- a/images/domain.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - StepDefinition - - - - Actor - - - - SessionInteraction - - - - DomainSession - - - - DomainLogic - - diff --git a/images/http-domain.svg b/images/http-domain.svg deleted file mode 100644 index f87cc9eb..00000000 --- a/images/http-domain.svg +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - StepDefinition - - - - Actor - - - - SessionInteraction - - - - HttpSession - - - - Network - - - - ExpressApp - - - - DomainLogic - - diff --git a/package-lock.json b/package-lock.json index 47f59cdf..7e7af9e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { - "name": "@cucumber/screenplay", - "version": "5.1.0", + "name": "@cucumber/screenplay-examples", + "version": "0.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "@cucumber/screenplay", - "version": "5.1.0", + "name": "@cucumber/screenplay-examples", + "version": "0.0.1", "license": "MIT", "devDependencies": { "@cucumber/cucumber": "^7.3.1", "@cucumber/electron": "4.1.3", "@cucumber/microdata": "2.1.0", + "@cucumber/screenplay": "^5.1.0", "@testing-library/dom": "8.19.0", "@testing-library/user-event": "13.5.0", "@types/eventsource": "1.1.9", @@ -46,9 +47,6 @@ "ts-node": "10.9.1", "typescript": "4.8.4", "uuid": "9.0.0" - }, - "peerDependencies": { - "@cucumber/cucumber": "^7.3.1" } }, "node_modules/@babel/code-frame": { @@ -358,6 +356,15 @@ "integrity": "sha512-Ut3TNZ9hmrkjPnUB0QyJqJeK2vnIajwbZ2sHRXwzBpRuKTmx0J4wSHGZxeLopNQJ9sYSGlGwXZrvIxp45LI1mg==", "dev": true }, + "node_modules/@cucumber/screenplay": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/screenplay/-/screenplay-5.1.0.tgz", + "integrity": "sha512-9MYAORJGZugZl98AD0Yfa62ehEAWEsdKMNfqYZEfybOvsihiUUP+o+1PPEm5BXE2zMT6db+0aYAfZ6sY/zwcjQ==", + "dev": true, + "peerDependencies": { + "@cucumber/cucumber": "^7.3.1" + } + }, "node_modules/@cucumber/tag-expressions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@cucumber/tag-expressions/-/tag-expressions-3.0.1.tgz", @@ -8832,6 +8839,13 @@ "integrity": "sha512-Ut3TNZ9hmrkjPnUB0QyJqJeK2vnIajwbZ2sHRXwzBpRuKTmx0J4wSHGZxeLopNQJ9sYSGlGwXZrvIxp45LI1mg==", "dev": true }, + "@cucumber/screenplay": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@cucumber/screenplay/-/screenplay-5.1.0.tgz", + "integrity": "sha512-9MYAORJGZugZl98AD0Yfa62ehEAWEsdKMNfqYZEfybOvsihiUUP+o+1PPEm5BXE2zMT6db+0aYAfZ6sY/zwcjQ==", + "dev": true, + "requires": {} + }, "@cucumber/tag-expressions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@cucumber/tag-expressions/-/tag-expressions-3.0.1.tgz", diff --git a/package.json b/package.json index 359d9de9..7216eec4 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,10 @@ { - "name": "@cucumber/screenplay", - "version": "5.1.0", - "description": "Write better scenarios with Cucumber.js", - "main": "dist/src/index.js", - "types": "dist/src/index.d.ts", - "dependencies": {}, - "peerDependencies": { - "@cucumber/cucumber": "^7.3.1" - }, + "name": "@cucumber/screenplay-examples", + "private": true, + "version": "0.0.1", + "description": "Examples for @cucumber/screenplay", "devDependencies": { + "@cucumber/screenplay": "^5.1.0", "@cucumber/cucumber": "^7.3.1", "@cucumber/electron": "4.1.3", "@cucumber/microdata": "2.1.0", @@ -49,13 +45,11 @@ }, "scripts": { "build": "tsc --build tsconfig.json", - "test": "npm run mocha && npm run cucumber && npm run cucumber-http && npm run cucumber-dom && npm run cucumber-dom-http", - "mocha": "mocha", + "test": "npm run cucumber && npm run cucumber-http && npm run cucumber-dom && npm run cucumber-dom-http", "cucumber": "cucumber-js", "cucumber-http": "cucumber-js --profile http", "cucumber-dom": "cucumber-electron --profile dom --stylesheet features/src/components/style.css ", "cucumber-dom-http": "cucumber-electron --profile domHttp --stylesheet features/src/components/style.css", - "prepublishOnly": "npm run build", "upgrade": "npm-check-updates --upgrade", "eslint": "eslint --ext ts,tsx --max-warnings 0 src features", "eslint-fix": "eslint --ext ts,tsx --max-warnings 0 --fix src features", @@ -63,7 +57,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/cucumber/screenplay.js.git" + "url": "git+https://github.com/cucumber/screenplay.js.examples.git" }, "keywords": [ "testing", @@ -74,9 +68,9 @@ "author": "Cucumber Team", "license": "MIT", "bugs": { - "url": "https://github.com/cucumber/screenplay.js/issues" + "url": "https://github.com/cucumber/screenplay.js.examples/issues" }, - "homepage": "https://github.com/cucumber/screenplay.js#readme", + "homepage": "https://github.com/cucumber/screenplay.js.examples#readme", "prettier": { "trailingComma": "es5", "semi": false, diff --git a/src/Actor.ts b/src/Actor.ts deleted file mode 100644 index 8e002026..00000000 --- a/src/Actor.ts +++ /dev/null @@ -1,34 +0,0 @@ -export type Action = (actor: Actor) => Answer -export type PromiseAction = (actor: Actor) => Promise - -export type DefaultFunction = () => T - -/** - * An Actor represents a user interacting with the system. - */ -export default class Actor { - private readonly memory = new Map() - constructor(public readonly world: World, public readonly name: string) {} - - public remember(key: string, value: T) { - this.memory.set(key, value) - } - - public recall(key: string, defaultFunction?: DefaultFunction): T { - if (!this.memory.has(key) && defaultFunction) { - this.memory.set(key, defaultFunction()) - } - return this.memory.get(key) as T - } - - public attemptsTo(action: Action): Answer { - return action(this) - } - - /** - * Just a synonym for attemptsTo - */ - public ask(action: Action): Answer { - return action(this) - } -} diff --git a/src/ActorLookup.ts b/src/ActorLookup.ts deleted file mode 100644 index da9254c9..00000000 --- a/src/ActorLookup.ts +++ /dev/null @@ -1,20 +0,0 @@ -import Actor from './Actor' - -export default class ActorLookup { - private readonly actorByName = new Map() - - public findOrCreateActor(world: unknown, actorName: string): Actor { - let actor = this.actorByName.get(actorName) - - if (actor === undefined) { - actor = new Actor(world, actorName) - this.actorByName.set(actorName, actor) - } - - return actor - } - - public get actors(): IterableIterator { - return this.actorByName.values() - } -} diff --git a/src/ActorParameterType.ts b/src/ActorParameterType.ts deleted file mode 100644 index c0943e3e..00000000 --- a/src/ActorParameterType.ts +++ /dev/null @@ -1,9 +0,0 @@ -import ActorWorld from './ActorWorld' - -export default { - name: 'actor', - regexp: /[A-Z][a-z]+/, - transformer(this: ActorWorld, actorName: string) { - return this.findOrCreateActor(actorName) - }, -} diff --git a/src/ActorWorld.ts b/src/ActorWorld.ts deleted file mode 100644 index b5c130f5..00000000 --- a/src/ActorWorld.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { World, IWorldOptions } from '@cucumber/cucumber' -import Actor from './Actor' -import ActorLookup from './ActorLookup' -import assignTasks from './assignTasks' - -export default class ActorWorld extends World { - public readonly actorLookup = new ActorLookup() - - constructor(props: IWorldOptions) { - super(props) - if (this.parameters.tasks) { - assignTasks(this, this.parameters.tasks) - } - } - - public findOrCreateActor(actorName: string): Actor { - return this.actorLookup.findOrCreateActor(this, actorName) - } -} diff --git a/features/src/HttpSession.ts b/src/HttpSession.ts similarity index 100% rename from features/src/HttpSession.ts rename to src/HttpSession.ts diff --git a/features/src/Inbox.ts b/src/Inbox.ts similarity index 100% rename from features/src/Inbox.ts rename to src/Inbox.ts diff --git a/features/src/Shouty.ts b/src/Shouty.ts similarity index 100% rename from features/src/Shouty.ts rename to src/Shouty.ts diff --git a/features/src/ShoutySession.ts b/src/ShoutySession.ts similarity index 100% rename from features/src/ShoutySession.ts rename to src/ShoutySession.ts diff --git a/src/assignTasks.ts b/src/assignTasks.ts deleted file mode 100644 index 73f33711..00000000 --- a/src/assignTasks.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { readdirSync } from 'fs' -import path from 'path' - -export default function assignTasks(thisObj: T, tasksDir: string): void { - if (!tasksDir) throw new Error(`tasksDir was ${tasksDir}`) - const files = readdirSync(tasksDir) - for (const file of files) { - const match = file.match(/(\.ts|\.js|\.tsx|\.jsx)$/) - if (match) { - const ext = match[1] - const name = path.basename(file, ext) - Object.defineProperty(thisObj, name, { - value: loadTask(name), - }) - } - } - - function loadTask(name: string) { - const path = `${tasksDir}/${name}` - try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const task = require(path) - return task[name] - } catch (err) { - return () => { - throw new Error(`No task in: ${path}.{ts,js,tsx,jsx}`) - } - } - } -} diff --git a/features/src/calculateDistance.ts b/src/calculateDistance.ts similarity index 100% rename from features/src/calculateDistance.ts rename to src/calculateDistance.ts diff --git a/features/src/components/App.tsx b/src/components/App.tsx similarity index 100% rename from features/src/components/App.tsx rename to src/components/App.tsx diff --git a/features/src/components/style.css b/src/components/style.css similarity index 100% rename from features/src/components/style.css rename to src/components/style.css diff --git a/src/eventually.ts b/src/eventually.ts deleted file mode 100644 index be80fc05..00000000 --- a/src/eventually.ts +++ /dev/null @@ -1,66 +0,0 @@ -export type Condition = () => Result | Promise - -export type EventuallyOptions = { - timeout?: number - interval?: number -} - -/** - * Waits for a condition to eventually pass without an error. - * The condition will pass regardless of the return value (including false, 0, undefined or null). - * The condition will run multiple times run until it passes or times out, depending on the timeout and interval values of options. - * - * @param condition - * @param options - */ -export default function eventually(condition: Condition, options?: EventuallyOptions): Promise { - const { interval, timeout } = { interval: 50, timeout: 1000, ...options } - - let lastError: Error | undefined = undefined - let intervalId: NodeJS.Timeout - let timeoutId: NodeJS.Timeout - - const conditionPromise = new Promise((resolve) => { - intervalId = setIntervalImmediately(() => { - try { - // If condition() does not return a Promise, this will convert it into one - // If condition() returns a Promise, this will just return the same promise - Promise.resolve(condition()) - .then((result) => resolve(result)) - .catch((err) => (lastError = err)) - } catch (err) { - // condition() threw an error (it was synchronous, not returning a Promise) - lastError = err - } - }, interval) - }) - - const timeoutPromise = new Promise( - (_, reject) => - (timeoutId = setTimeout(() => { - reject(lastError || new Error(`Timeout after ${timeout}ms`)) - }, timeout)) - ) - - return new Promise((resolve, reject) => { - Promise.race([conditionPromise, timeoutPromise]) - .then((result) => { - clearInterval(intervalId) - clearTimeout(timeoutId) - resolve(result) - }) - .catch((err) => { - clearInterval(intervalId) - clearTimeout(timeoutId) - reject(err) - }) - }) -} - -// setInterval does not invoke the function immediately, but waits for the first interval. -// This function makes sure it is called immediately. -function setIntervalImmediately(callback: (...args: unknown[]) => void, ms: number) { - const iv = setInterval(callback, ms) - callback() - return iv -} diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index a4a9e7cc..00000000 --- a/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Actor, { Action, PromiseAction } from './Actor' -import ActorParameterType from './ActorParameterType' -import ActorWorld from './ActorWorld' -import eventually from './eventually' - -export type { Action, PromiseAction } -export { Actor, ActorWorld, ActorParameterType, eventually } diff --git a/features/src/server.ts b/src/server.ts similarity index 100% rename from features/src/server.ts rename to src/server.ts diff --git a/features/src/types.ts b/src/types.ts similarity index 100% rename from features/src/types.ts rename to src/types.ts diff --git a/test/eventually.test.ts b/test/eventually.test.ts deleted file mode 100644 index 98c580e3..00000000 --- a/test/eventually.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import assert = require('assert') -import eventually, { Condition, EventuallyOptions } from '../src/eventually' - -const options: Required = { - timeout: 100, - interval: 2, -} - -describe('eventually', () => { - describe('without Promise', () => { - it('resolves immediately when condition does not throw', async () => { - const condition: Condition = () => 42 - const result = await eventually(condition) - assert.strictEqual(result, 42) - }) - - it('resolves immediately even if condition returns false', async () => { - const condition: Condition = () => false - const result = await eventually(condition) - assert.strictEqual(result, false) - }) - - it('resolves eventually after rejecting first', async () => { - let n = 40 - const condition: Condition = () => { - assert.strictEqual(n++, 42) - return 'ok' - } - const result = await eventually(condition, options) - assert.strictEqual(result, 'ok') - }) - - it('rejects with the last error when the timeout has elapsed', async () => { - const condition: Condition = () => { - assert.strictEqual(10, 42) - return 'ok' - } - await assert.rejects(eventually(condition, options), { - message: 'Expected values to be strictly equal:\n\n10 !== 42\n', - }) - }) - - it('rejects with a timeout error when the condition never settles', async () => { - const condition: Condition = () => new Promise((resolve) => setTimeout(resolve, options.timeout * 2)) - await assert.rejects(eventually(condition, options), { message: `Timeout after ${options.timeout}ms` }) - }) - }) - - describe('with Promise', () => { - it('resolves immediately when condition does not throw', async () => { - const condition: Condition = () => Promise.resolve(42) - const result = await eventually(condition) - assert.strictEqual(result, 42) - }) - - it('resolves immediately even if condition returns false', async () => { - const condition: Condition = () => Promise.resolve(false) - const result = await eventually(condition) - assert.strictEqual(result, false) - }) - - it('resolves eventually after rejecting first', async () => { - let n = 40 - const condition: Condition = async () => { - assert.strictEqual(n++, 42) - return 'ok' - } - const result = await eventually(condition, options) - assert.strictEqual(result, 'ok') - }) - - it('rejects with the last error when the timeout has elapsed', async () => { - const condition: Condition = async () => { - assert.strictEqual(10, 42) - return 'ok' - } - await assert.rejects(eventually(condition, options), { - message: 'Expected values to be strictly equal:\n\n10 !== 42\n', - }) - }) - - it('rejects with a timeout error when the condition never settles', async () => { - const condition: Condition = () => new Promise((resolve) => setTimeout(resolve, options.timeout * 2)) - await assert.rejects(eventually(condition, options), { message: `Timeout after ${options.timeout}ms` }) - }) - }) -})