From: Ruben Beltran del Rio Date: Sat, 30 Apr 2022 23:02:58 +0000 (+0200) Subject: Apply formatting X-Git-Url: https://git.r.bdr.sh/rbdr/forum/commitdiff_plain/cac85db02ff00732cf75d473dc3411332f33d845?hp=a7cf03c192470cbab13edeb1aec99e0c66dede10 Apply formatting --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 703003c..b1f4357 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ stages: - test before_script: - - npm install + - npm install lint: stage: lint diff --git a/CHANGELOG.md b/CHANGELOG.md index 6395a24..40512a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,14 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] + ### Added + - Svelte based frontend - Koa based backend - RethinkDB for backend @@ -17,4 +20,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - NPM tasks to lint and install git hooks - A gitignore file -[Unreleased]: https://gitlab.com/rbdr/forum/compare/master...develop +[unreleased]: https://gitlab.com/rbdr/forum/compare/master...develop diff --git a/README.md b/README.md index e8b6201..3e0f099 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,11 @@ You can run tests with `npm test`. The tests use `testing-library`, `pact`, and `jest`. Here's some short guidelines: - - Every component that receives props or changes state should be tested. - - Test expected outcomes, not implementation details. - - Avoid mocking unless it's an external call - - Stores that interact with the API should be tested using pact + +- Every component that receives props or changes state should be tested. +- Test expected outcomes, not implementation details. +- Avoid mocking unless it's an external call +- Stores that interact with the API should be tested using pact [node]: https://nodejs.org/en/ [forum-server]: https://gitlab.com/rbdr/forum-server diff --git a/doc/COVERAGE.md b/doc/COVERAGE.md index dd1f5ef..09d8810 100644 --- a/doc/COVERAGE.md +++ b/doc/COVERAGE.md @@ -1,31 +1,29 @@ -# Code Quality Report -Thu Nov 15 2018 01:45:42 GMT+0100 (Central European Standard Time) - +# Code Quality Report + +Thu Nov 15 2018 01:45:42 GMT+0100 (Central European Standard Time) + ## Tests - + **Application Loader** -✔ 1) Should instantiate and start Forum on window load (18 ms) - - +✔ 1) Should instantiate and start Forum on window load (18 ms) + 1 test 0 tests failed -0 tests skipped - -Test duration: 27 ms - - -## Leaks -The following global variable leaks were detected:_registeredHandlers, _eventHandlers, DOMException, NamedNodeMap, Attr, Node, Element, DocumentFragment, HTMLDocument, Document, XMLDocument, CharacterData, Text, CDATASection, ProcessingInstruction, Comment, DocumentType, DOMImplementation, NodeList, HTMLCollection, HTMLOptionsCollection, DOMStringMap, DOMTokenList, SVGAnimatedString, SVGNumber, SVGStringList, Event, CloseEvent, CustomEvent, MessageEvent, ErrorEvent, HashChangeEvent, FocusEvent, PopStateEvent, UIEvent, MouseEvent, KeyboardEvent, TouchEvent, ProgressEvent, CompositionEvent, WheelEvent, EventTarget, BarProp, Location, History, Screen, Performance, Blob, File, FileList, DOMParser, FormData, XMLHttpRequestEventTarget, XMLHttpRequestUpload, NodeIterator, TreeWalker, HTMLElement, HTMLAnchorElement, HTMLAreaElement, HTMLAudioElement, HTMLBaseElement, HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDataElement, HTMLDataListElement, HTMLDetailsElement, HTMLDialogElement, HTMLDirectoryElement, HTMLDivElement, HTMLDListElement, HTMLEmbedElement, HTMLFieldSetElement, HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, HTMLHeadingElement, HTMLHeadElement, HTMLHRElement, HTMLHtmlElement, HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLLabelElement, HTMLLegendElement, HTMLLIElement, HTMLLinkElement, HTMLMapElement, HTMLMarqueeElement, HTMLMediaElement, HTMLMenuElement, HTMLMetaElement, HTMLMeterElement, HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, HTMLOptionElement, HTMLOutputElement, HTMLParagraphElement, HTMLParamElement, HTMLPictureElement, HTMLPreElement, HTMLProgressElement, HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLSourceElement, HTMLSpanElement, HTMLStyleElement, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, HTMLTableElement, HTMLTimeElement, HTMLTitleElement, HTMLTableRowElement, HTMLTableSectionElement, HTMLTemplateElement, HTMLTextAreaElement, HTMLTrackElement, HTMLUListElement, HTMLUnknownElement, HTMLVideoElement, SVGElement, SVGGraphicsElement, SVGSVGElement, StyleSheet, MediaList, CSSStyleSheet, CSSRule, CSSStyleRule, CSSMediaRule, CSSImportRule, CSSStyleDeclaration, StyleSheetList, XPathException, XPathExpression, XPathResult, XPathEvaluator, NodeFilter, Window, _globalProxy, _document, _sessionHistory, _virtualConsole, _runScripts, _top, _parent, _frameElement, _length, _pretendToBeVisual, length, window, frameElement, frames, self, parent, top, document, external, location, history, navigator, locationbar, menubar, personalbar, scrollbars, statusbar, toolbar, performance, screen, addEventListener, removeEventListener, dispatchEvent, __stopAllTimers, Option, Image, Audio, postMessage, atob, btoa, FileReader, WebSocket, AbortSignal, AbortController, XMLHttpRequest, stop, close, getComputedStyle, captureEvents, releaseEvents, name, devicePixelRatio, innerWidth, innerHeight, outerWidth, outerHeight, pageXOffset, pageYOffset, screenX, screenY, scrollX, scrollY, screenLeft, screenTop, alert, blur, confirm, focus, moveBy, moveTo, open, print, prompt, resizeBy, resizeTo, scroll, scrollBy, scrollTo - - -## Coverage +0 tests skipped + +Test duration: 27 ms + +## Leaks + +The following global variable leaks were detected:\_registeredHandlers, \_eventHandlers, DOMException, NamedNodeMap, Attr, Node, Element, DocumentFragment, HTMLDocument, Document, XMLDocument, CharacterData, Text, CDATASection, ProcessingInstruction, Comment, DocumentType, DOMImplementation, NodeList, HTMLCollection, HTMLOptionsCollection, DOMStringMap, DOMTokenList, SVGAnimatedString, SVGNumber, SVGStringList, Event, CloseEvent, CustomEvent, MessageEvent, ErrorEvent, HashChangeEvent, FocusEvent, PopStateEvent, UIEvent, MouseEvent, KeyboardEvent, TouchEvent, ProgressEvent, CompositionEvent, WheelEvent, EventTarget, BarProp, Location, History, Screen, Performance, Blob, File, FileList, DOMParser, FormData, XMLHttpRequestEventTarget, XMLHttpRequestUpload, NodeIterator, TreeWalker, HTMLElement, HTMLAnchorElement, HTMLAreaElement, HTMLAudioElement, HTMLBaseElement, HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDataElement, HTMLDataListElement, HTMLDetailsElement, HTMLDialogElement, HTMLDirectoryElement, HTMLDivElement, HTMLDListElement, HTMLEmbedElement, HTMLFieldSetElement, HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, HTMLHeadingElement, HTMLHeadElement, HTMLHRElement, HTMLHtmlElement, HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLLabelElement, HTMLLegendElement, HTMLLIElement, HTMLLinkElement, HTMLMapElement, HTMLMarqueeElement, HTMLMediaElement, HTMLMenuElement, HTMLMetaElement, HTMLMeterElement, HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, HTMLOptionElement, HTMLOutputElement, HTMLParagraphElement, HTMLParamElement, HTMLPictureElement, HTMLPreElement, HTMLProgressElement, HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLSourceElement, HTMLSpanElement, HTMLStyleElement, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, HTMLTableElement, HTMLTimeElement, HTMLTitleElement, HTMLTableRowElement, HTMLTableSectionElement, HTMLTemplateElement, HTMLTextAreaElement, HTMLTrackElement, HTMLUListElement, HTMLUnknownElement, HTMLVideoElement, SVGElement, SVGGraphicsElement, SVGSVGElement, StyleSheet, MediaList, CSSStyleSheet, CSSRule, CSSStyleRule, CSSMediaRule, CSSImportRule, CSSStyleDeclaration, StyleSheetList, XPathException, XPathExpression, XPathResult, XPathEvaluator, NodeFilter, Window, \_globalProxy, \_document, \_sessionHistory, \_virtualConsole, \_runScripts, \_top, \_parent, \_frameElement, \_length, \_pretendToBeVisual, length, window, frameElement, frames, self, parent, top, document, external, location, history, navigator, locationbar, menubar, personalbar, scrollbars, statusbar, toolbar, performance, screen, addEventListener, removeEventListener, dispatchEvent, \_\_stopAllTimers, Option, Image, Audio, postMessage, atob, btoa, FileReader, WebSocket, AbortSignal, AbortController, XMLHttpRequest, stop, close, getComputedStyle, captureEvents, releaseEvents, name, devicePixelRatio, innerWidth, innerHeight, outerWidth, outerHeight, pageXOffset, pageYOffset, screenX, screenY, scrollX, scrollY, screenLeft, screenTop, alert, blur, confirm, focus, moveBy, moveTo, open, print, prompt, resizeBy, resizeTo, scroll, scrollBy, scrollTo + +## Coverage + Threshold: 100% -Coverage: 0.00% (0/0) - - - -## Linting +Coverage: 0.00% (0/0) + +## Linting + Warnings threshold: 0 Errors threshold: 0 -No issues - +No issues diff --git a/doc/README.md b/doc/README.md index f294b0f..d3119e0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -25,16 +25,17 @@ the forum object.

## Forum -The Forum class is the main entry point for the backend application. +The Forum class is the main entry point for the backend application. -| Param | Type | Description | -| --- | --- | --- | +| Param | Type | Description | +| ------ | ---------------------------------------------------------------------- | ------------------------------------------------- | | config | [tForumBackendConfiguration](#tForumBackendConfiguration) | the initialization options to extend the instance | ### forum.run() + Initializes the application and starts listening. Also prints a nice robotic banner with information. @@ -42,6 +43,7 @@ nice robotic banner with information. ## tForumBackendConfiguration : object + The main configuration object for the Forum backend. It will be used to initialize all of the sub-components. It can extend any property of the forum object. @@ -49,37 +51,38 @@ the forum object. **Kind**: global typedef **Properties** -| Name | Type | Default | Description | -| --- | --- | --- | --- | -| [port] | number | 1978 | the port where the app will listen on | -| [staticDirectory] | string | "static" | the path, relative to the project root, where static assets live | -| [ttl] | number | 180 | the time in seconds that posts remain alive | -| rethinkDB | [tRethinkDBConfiguration](#tRethinkDBConfiguration) | | the configuration to connect to the rethinkDB server | -| jwt | [tJWTConfiguration](#tJWTConfiguration) | | the configuration for the JWT authentication | +| Name | Type | Default | Description | +| ----------------- | ---------------------------------------------------------------- | ------------------------------- | ---------------------------------------------------------------- | +| [port] | number | 1978 | the port where the app will listen on | +| [staticDirectory] | string | "static" | the path, relative to the project root, where static assets live | +| [ttl] | number | 180 | the time in seconds that posts remain alive | +| rethinkDB | [tRethinkDBConfiguration](#tRethinkDBConfiguration) | | the configuration to connect to the rethinkDB server | +| jwt | [tJWTConfiguration](#tJWTConfiguration) | | the configuration for the JWT authentication | ## tJWTConfiguration : object + Configures the behavior of the JWT token. **Kind**: global typedef **Properties** -| Name | Type | Default | Description | -| --- | --- | --- | --- | +| Name | Type | Default | Description | +| ---------- | ------------------- | ------------------ | ---------------------------------- | | [duration] | number | 86400 | the duration of the JWT in seconds | -| secret | string | | the secret used to sign the JWT | +| secret | string | | the secret used to sign the JWT | ## tRethinkDBConfiguration : object + Information required to connect to the rethinkDB server **Kind**: global typedef **Properties** -| Name | Type | Default | Description | -| --- | --- | --- | --- | -| host | string | | the location of the rethinkDB host | +| Name | Type | Default | Description | +| ------ | ------------------- | ----------------- | ---------------------------------------- | +| host | string | | the location of the rethinkDB host | | [post] | string | 6379 | port where rethinkDB server is listening | - diff --git a/jest.config.js b/jest.config.js index 6b808fc..0e21d6b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,24 +1,24 @@ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ export default { - preset: "ts-jest", - transform: { - "^.+\\.svelte$": [ - "svelte-jester", - { - "preprocess": true - } - ] - }, - moduleNameMapper: { - "^\\$lib(.*)$": "/src/lib$1", - "^\\$app(.*)$": [".svelte/dev/runtime/app/*", ".svelte/build/runtime/app/*"] - }, - moduleFileExtensions: ["ts", "js", "svelte"], - globals: { - 'ts-jest': { - diagnostics: { - ignoreCodes: [ 'TS151001' ], - }, - }, - }, -} + preset: 'ts-jest', + transform: { + '^.+\\.svelte$': [ + 'svelte-jester', + { + preprocess: true + } + ] + }, + moduleNameMapper: { + '^\\$lib(.*)$': '/src/lib$1', + '^\\$app(.*)$': ['.svelte/dev/runtime/app/*', '.svelte/build/runtime/app/*'] + }, + moduleFileExtensions: ['ts', 'js', 'svelte'], + globals: { + 'ts-jest': { + diagnostics: { + ignoreCodes: ['TS151001'] + } + } + } +}; diff --git a/pacts/forumclient-forumserver.json b/pacts/forumclient-forumserver.json index 9ec37f8..c4d529c 100644 --- a/pacts/forumclient-forumserver.json +++ b/pacts/forumclient-forumserver.json @@ -1,983 +1,972 @@ { - "consumer": { - "name": "ForumClient" - }, - "provider": { - "name": "ForumServer" - }, - "interactions": [ - { - "description": "a request to list the forums", - "providerState": "there's data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForums", - "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", - "variables": { - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "forums": [ - { - "id": "butter", - "glyph": "⌘", - "label": "test_forums.butter", - "position": 1 - } - ] - } - }, - "matchingRules": { - "$.body.data.forums": { - "min": 1 - }, - "$.body.data.forums[*].*": { - "match": "type" - }, - "$.body.data.forums[*].id": { - "match": "type" - }, - "$.body.data.forums[*].glyph": { - "match": "type" - }, - "$.body.data.forums[*].label": { - "match": "type" - }, - "$.body.data.forums[*].position": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single forum", - "providerState": "there's data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForum", - "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "freezer" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "forum": { - "id": "freezer", - "glyph": "✭", - "label": "test_forums.freezer", - "position": 3, - "topics": [ - { - "id": "629de02c-151a-4db7-bb86-43b2add8a15a", - "title": "Very pacty topic", - "updated_at": 1619954611616, - "ttl": 3601 - } - ] - } - } - }, - "matchingRules": { - "$.body.data.forum": { - "match": "type" - }, - "$.body.data.forum.glyph": { - "match": "type" - }, - "$.body.data.forum.label": { - "match": "type" - }, - "$.body.data.forum.position": { - "match": "type" - }, - "$.body.data.forum.topics": { - "min": 1 - }, - "$.body.data.forum.topics[*].*": { - "match": "type" - }, - "$.body.data.forum.topics[*].id": { - "match": "type" - }, - "$.body.data.forum.topics[*].title": { - "match": "type" - }, - "$.body.data.forum.topics[*].updated_at": { - "match": "type" - }, - "$.body.data.forum.topics[*].ttl": { - "match": "type" - } - } - } - }, - { - "description": "a request to list the forums", - "providerState": "there's no data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForums", - "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", - "variables": { - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "forums": [ - - ] - } - } - } - }, - { - "description": "a request to get a single forum", - "providerState": "there's no data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForum", - "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "freezer" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "forum": null - } - } - } - }, - { - "description": "a request to list the forums", - "providerState": "there's a server error", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForums", - "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", - "variables": { - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 500, - "headers": { - } - } - }, - { - "description": "a request to get a single forum", - "providerState": "there's a server error", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForum", - "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "freezer" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 500, - "headers": { - } - } - }, - { - "description": "a request to list the forums", - "providerState": "there's an error in the response", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForums", - "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", - "variables": { - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "errors": [ - { - "message": "An error occurred when fetching forums" - } - ] - }, - "matchingRules": { - "$.body.errors": { - "min": 1 - }, - "$.body.errors[*].*": { - "match": "type" - }, - "$.body.errors[*].message": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single forum", - "providerState": "there's an error in the response", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetForum", - "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "freezer" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "errors": [ - { - "message": "An error occurred when fetching the forum" - } - ] - }, - "matchingRules": { - "$.body.errors": { - "min": 1 - }, - "$.body.errors[*].*": { - "match": "type" - }, - "$.body.errors[*].message": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single topic", - "providerState": "there's data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTopic", - "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "topic": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1", - "title": "The pacty topic of the day", - "updated_at": 1619979888906, - "ttl": 3399, - "forum": { - "id": "cucumber", - "glyph": "✽", - "label": "test_forums.cucumber" - }, - "tags": [ - { - "id": "skunk", - "weight": 44 - } - ], - "posts": [ - { - "id": "ed93530e-6f9c-4701-91ef-14f9e0ed3e26", - "text": "The content of this post is very relevant", - "created_at": 1619979889798, - "author": { - "id": "07fb2ba0-0945-464a-b215-873296710c8c", - "handle": "cucumber_fan92" - } - } - ] - } - } - }, - "matchingRules": { - "$.body.data.topic.id": { - "match": "type" - }, - "$.body.data.topic.title": { - "match": "type" - }, - "$.body.data.topic.updated_at": { - "match": "type" - }, - "$.body.data.topic.ttl": { - "match": "type" - }, - "$.body.data.topic.forum.id": { - "match": "type" - }, - "$.body.data.topic.forum.glyph": { - "match": "type" - }, - "$.body.data.topic.forum.label": { - "match": "type" - }, - "$.body.data.topic.tags": { - "min": 1 - }, - "$.body.data.topic.tags[*].*": { - "match": "type" - }, - "$.body.data.topic.tags[*].id": { - "match": "type" - }, - "$.body.data.topic.tags[*].weight": { - "match": "type" - }, - "$.body.data.topic.posts": { - "min": 1 - }, - "$.body.data.topic.posts[*].*": { - "match": "type" - }, - "$.body.data.topic.posts[*].id": { - "match": "type" - }, - "$.body.data.topic.posts[*].text": { - "match": "type" - }, - "$.body.data.topic.posts[*].created_at": { - "match": "type" - }, - "$.body.data.topic.posts[*].author": { - "match": "type" - }, - "$.body.data.topic.posts[*].author.id": { - "match": "type" - }, - "$.body.data.topic.posts[*].author.handle": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single topic", - "providerState": "there's no data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTopic", - "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "topic": null - } - } - } - }, - { - "description": "a request to get a single topic", - "providerState": "there's a server error", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTopic", - "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 500, - "headers": { - } - } - }, - { - "description": "a request to get a single topic", - "providerState": "there's an error in the response", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTopic", - "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "errors": [ - { - "message": "An error occurred when fetching the topic" - } - ] - }, - "matchingRules": { - "$.body.errors": { - "min": 1 - }, - "$.body.errors[*].*": { - "match": "type" - }, - "$.body.errors[*].message": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single tag", - "providerState": "there's data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTag", - "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "pineapple" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "tag": { - "id": "pineapple", - "topics": [ - { - "id": "cd038ae7-e8b4-4e38-9543-3d697e69ac34", - "title": "This topic is about pineapples", - "updated_at": 1619978944077, - "ttl": 3555 - } - ] - } - } - }, - "matchingRules": { - "$.body.data.tag.id": { - "match": "type" - }, - "$.body.data.tag.topics": { - "min": 1 - }, - "$.body.data.tag.topics[*].*": { - "match": "type" - }, - "$.body.data.tag.topics[*].id": { - "match": "type" - }, - "$.body.data.tag.topics[*].title": { - "match": "type" - }, - "$.body.data.tag.topics[*].updated_at": { - "match": "type" - }, - "$.body.data.tag.topics[*].ttl": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single tag", - "providerState": "there's no data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTag", - "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "pineapple" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "tag": null - } - } - } - }, - { - "description": "a request to get a single tag", - "providerState": "there's a server error", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTag", - "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "pineapple" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 500, - "headers": { - } - } - }, - { - "description": "a request to get a single tag", - "providerState": "there's an error in the response", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetTag", - "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "pineapple" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "errors": [ - { - "message": "An error occurred when fetching the tag" - } - ] - }, - "matchingRules": { - "$.body.errors": { - "min": 1 - }, - "$.body.errors[*].*": { - "match": "type" - }, - "$.body.errors[*].message": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single post", - "providerState": "there's data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetPost", - "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "post": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374", - "text": "This is a very pacty post", - "created_at": 1619976194937, - "author": { - "id": "a805b3de-cac4-451c-a1e6-f078869c9db9", - "handle": "pacts_person" - }, - "topic": { - "id": "5c283ce1-0470-4b98-86f5-1fec9a22c9ac", - "title": "The parent pacts topic" - } - } - } - }, - "matchingRules": { - "$.body.data.post": { - "match": "type" - }, - "$.body.data.post.id": { - "match": "type" - }, - "$.body.data.post.text": { - "match": "type" - }, - "$.body.data.post.created_at": { - "match": "type" - }, - "$.body.data.post.author": { - "match": "type" - }, - "$.body.data.post.author.id": { - "match": "type" - }, - "$.body.data.post.author.handle": { - "match": "type" - }, - "$.body.data.post.topic": { - "match": "type" - }, - "$.body.data.post.topic.id": { - "match": "type" - }, - "$.body.data.post.topic.title": { - "match": "type" - } - } - } - }, - { - "description": "a request to get a single post", - "providerState": "there's no data", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetPost", - "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "data": { - "post": null - } - } - } - }, - { - "description": "a request to get a single post", - "providerState": "there's a server error", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetPost", - "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 500, - "headers": { - } - } - }, - { - "description": "a request to get a single post", - "providerState": "there's an error in the response", - "request": { - "method": "POST", - "path": "/graphql", - "headers": { - "content-type": "application/json" - }, - "body": { - "operationName": "GetPost", - "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", - "variables": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374" - } - }, - "matchingRules": { - "$.body.query": { - "match": "regex", - "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" - } - } - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/json; charset=utf-8" - }, - "body": { - "errors": [ - { - "message": "An error occurred when fetching the post" - } - ] - }, - "matchingRules": { - "$.body.errors": { - "min": 1 - }, - "$.body.errors[*].*": { - "match": "type" - }, - "$.body.errors[*].message": { - "match": "type" - } - } - } - } - ], - "metadata": { - "pactSpecification": { - "version": "2.0.0" - } - } -} \ No newline at end of file + "consumer": { + "name": "ForumClient" + }, + "provider": { + "name": "ForumServer" + }, + "interactions": [ + { + "description": "a request to list the forums", + "providerState": "there's data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForums", + "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", + "variables": {} + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "forums": [ + { + "id": "butter", + "glyph": "⌘", + "label": "test_forums.butter", + "position": 1 + } + ] + } + }, + "matchingRules": { + "$.body.data.forums": { + "min": 1 + }, + "$.body.data.forums[*].*": { + "match": "type" + }, + "$.body.data.forums[*].id": { + "match": "type" + }, + "$.body.data.forums[*].glyph": { + "match": "type" + }, + "$.body.data.forums[*].label": { + "match": "type" + }, + "$.body.data.forums[*].position": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single forum", + "providerState": "there's data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForum", + "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "freezer" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "forum": { + "id": "freezer", + "glyph": "✭", + "label": "test_forums.freezer", + "position": 3, + "topics": [ + { + "id": "629de02c-151a-4db7-bb86-43b2add8a15a", + "title": "Very pacty topic", + "updated_at": 1619954611616, + "ttl": 3601 + } + ] + } + } + }, + "matchingRules": { + "$.body.data.forum": { + "match": "type" + }, + "$.body.data.forum.glyph": { + "match": "type" + }, + "$.body.data.forum.label": { + "match": "type" + }, + "$.body.data.forum.position": { + "match": "type" + }, + "$.body.data.forum.topics": { + "min": 1 + }, + "$.body.data.forum.topics[*].*": { + "match": "type" + }, + "$.body.data.forum.topics[*].id": { + "match": "type" + }, + "$.body.data.forum.topics[*].title": { + "match": "type" + }, + "$.body.data.forum.topics[*].updated_at": { + "match": "type" + }, + "$.body.data.forum.topics[*].ttl": { + "match": "type" + } + } + } + }, + { + "description": "a request to list the forums", + "providerState": "there's no data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForums", + "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", + "variables": {} + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "forums": [] + } + } + } + }, + { + "description": "a request to get a single forum", + "providerState": "there's no data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForum", + "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "freezer" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "forum": null + } + } + } + }, + { + "description": "a request to list the forums", + "providerState": "there's a server error", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForums", + "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", + "variables": {} + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 500, + "headers": {} + } + }, + { + "description": "a request to get a single forum", + "providerState": "there's a server error", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForum", + "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "freezer" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 500, + "headers": {} + } + }, + { + "description": "a request to list the forums", + "providerState": "there's an error in the response", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForums", + "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", + "variables": {} + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "errors": [ + { + "message": "An error occurred when fetching forums" + } + ] + }, + "matchingRules": { + "$.body.errors": { + "min": 1 + }, + "$.body.errors[*].*": { + "match": "type" + }, + "$.body.errors[*].message": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single forum", + "providerState": "there's an error in the response", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForum", + "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "freezer" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "errors": [ + { + "message": "An error occurred when fetching the forum" + } + ] + }, + "matchingRules": { + "$.body.errors": { + "min": 1 + }, + "$.body.errors[*].*": { + "match": "type" + }, + "$.body.errors[*].message": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single topic", + "providerState": "there's data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "topic": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1", + "title": "The pacty topic of the day", + "updated_at": 1619979888906, + "ttl": 3399, + "forum": { + "id": "cucumber", + "glyph": "✽", + "label": "test_forums.cucumber" + }, + "tags": [ + { + "id": "skunk", + "weight": 44 + } + ], + "posts": [ + { + "id": "ed93530e-6f9c-4701-91ef-14f9e0ed3e26", + "text": "The content of this post is very relevant", + "created_at": 1619979889798, + "author": { + "id": "07fb2ba0-0945-464a-b215-873296710c8c", + "handle": "cucumber_fan92" + } + } + ] + } + } + }, + "matchingRules": { + "$.body.data.topic.id": { + "match": "type" + }, + "$.body.data.topic.title": { + "match": "type" + }, + "$.body.data.topic.updated_at": { + "match": "type" + }, + "$.body.data.topic.ttl": { + "match": "type" + }, + "$.body.data.topic.forum.id": { + "match": "type" + }, + "$.body.data.topic.forum.glyph": { + "match": "type" + }, + "$.body.data.topic.forum.label": { + "match": "type" + }, + "$.body.data.topic.tags": { + "min": 1 + }, + "$.body.data.topic.tags[*].*": { + "match": "type" + }, + "$.body.data.topic.tags[*].id": { + "match": "type" + }, + "$.body.data.topic.tags[*].weight": { + "match": "type" + }, + "$.body.data.topic.posts": { + "min": 1 + }, + "$.body.data.topic.posts[*].*": { + "match": "type" + }, + "$.body.data.topic.posts[*].id": { + "match": "type" + }, + "$.body.data.topic.posts[*].text": { + "match": "type" + }, + "$.body.data.topic.posts[*].created_at": { + "match": "type" + }, + "$.body.data.topic.posts[*].author": { + "match": "type" + }, + "$.body.data.topic.posts[*].author.id": { + "match": "type" + }, + "$.body.data.topic.posts[*].author.handle": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single topic", + "providerState": "there's no data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "topic": null + } + } + } + }, + { + "description": "a request to get a single topic", + "providerState": "there's a server error", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 500, + "headers": {} + } + }, + { + "description": "a request to get a single topic", + "providerState": "there's an error in the response", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "errors": [ + { + "message": "An error occurred when fetching the topic" + } + ] + }, + "matchingRules": { + "$.body.errors": { + "min": 1 + }, + "$.body.errors[*].*": { + "match": "type" + }, + "$.body.errors[*].message": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single tag", + "providerState": "there's data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTag", + "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "pineapple" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "tag": { + "id": "pineapple", + "topics": [ + { + "id": "cd038ae7-e8b4-4e38-9543-3d697e69ac34", + "title": "This topic is about pineapples", + "updated_at": 1619978944077, + "ttl": 3555 + } + ] + } + } + }, + "matchingRules": { + "$.body.data.tag.id": { + "match": "type" + }, + "$.body.data.tag.topics": { + "min": 1 + }, + "$.body.data.tag.topics[*].*": { + "match": "type" + }, + "$.body.data.tag.topics[*].id": { + "match": "type" + }, + "$.body.data.tag.topics[*].title": { + "match": "type" + }, + "$.body.data.tag.topics[*].updated_at": { + "match": "type" + }, + "$.body.data.tag.topics[*].ttl": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single tag", + "providerState": "there's no data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTag", + "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "pineapple" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "tag": null + } + } + } + }, + { + "description": "a request to get a single tag", + "providerState": "there's a server error", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTag", + "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "pineapple" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 500, + "headers": {} + } + }, + { + "description": "a request to get a single tag", + "providerState": "there's an error in the response", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetTag", + "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "pineapple" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "errors": [ + { + "message": "An error occurred when fetching the tag" + } + ] + }, + "matchingRules": { + "$.body.errors": { + "min": 1 + }, + "$.body.errors[*].*": { + "match": "type" + }, + "$.body.errors[*].message": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single post", + "providerState": "there's data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "post": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374", + "text": "This is a very pacty post", + "created_at": 1619976194937, + "author": { + "id": "a805b3de-cac4-451c-a1e6-f078869c9db9", + "handle": "pacts_person" + }, + "topic": { + "id": "5c283ce1-0470-4b98-86f5-1fec9a22c9ac", + "title": "The parent pacts topic" + } + } + } + }, + "matchingRules": { + "$.body.data.post": { + "match": "type" + }, + "$.body.data.post.id": { + "match": "type" + }, + "$.body.data.post.text": { + "match": "type" + }, + "$.body.data.post.created_at": { + "match": "type" + }, + "$.body.data.post.author": { + "match": "type" + }, + "$.body.data.post.author.id": { + "match": "type" + }, + "$.body.data.post.author.handle": { + "match": "type" + }, + "$.body.data.post.topic": { + "match": "type" + }, + "$.body.data.post.topic.id": { + "match": "type" + }, + "$.body.data.post.topic.title": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single post", + "providerState": "there's no data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "post": null + } + } + } + }, + { + "description": "a request to get a single post", + "providerState": "there's a server error", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 500, + "headers": {} + } + }, + { + "description": "a request to get a single post", + "providerState": "there's an error in the response", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "errors": [ + { + "message": "An error occurred when fetching the post" + } + ] + }, + "matchingRules": { + "$.body.errors": { + "min": 1 + }, + "$.body.errors[*].*": { + "match": "type" + }, + "$.body.errors[*].message": { + "match": "type" + } + } + } + } + ], + "metadata": { + "pactSpecification": { + "version": "2.0.0" + } + } +} diff --git a/postcss.config.cjs b/postcss.config.cjs index 33ad091..054c147 100644 --- a/postcss.config.cjs +++ b/postcss.config.cjs @@ -1,6 +1,6 @@ module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/src/lib/animations/blink.test.ts b/src/lib/animations/blink.test.ts index 32dc872..b4d9f33 100644 --- a/src/lib/animations/blink.test.ts +++ b/src/lib/animations/blink.test.ts @@ -6,102 +6,88 @@ import { blink } from './blink'; import { sineOut } from 'svelte/easing'; const internals = { - response: null + response: null }; describe('blink', () => { - - test('it has a default delay of 0ms', () => { - - const response = blink(document.createElement('div'), {}); - - expect(response.delay).toBe(0); - }); - - test('it allows delay to be overridden', () => { - - const response = blink(document.createElement('div'), { - delay: 300 - }); - - expect(response.delay).toBe(300); - }); - - test('it has a default duration of 400ms', () => { - - const response = blink(document.createElement('div'), {}); - - expect(response.duration).toBe(400); - }); - - test('it allows delay to be overridden', () => { - - const response = blink(document.createElement('div'), { - duration: 999 - }); - - expect(response.duration).toBe(999); - }); - - test('it uses sineOut as the default easing function', () => { - - const response = blink(document.createElement('div'), {}); - - expect(response.easing).toBe(sineOut); - }); - - test('it allows easing function to be overridden', () => { - - const response = blink(document.createElement('div'), { - easing: () => 666 - }); - - expect(response.easing(0)).toBe(666); - }); - - describe('css animation function', () => { - - beforeEach(() => { - - const div = document.createElement('div'); - div.style.width = '100px'; - div.style.height = '200px'; - internals.response = blink(div, {}); - }); - - test('It starts with with zeroed width and height', () => { - - const css = internals.response.css(0, 1); - expect(css).toContain('width: 0px'); - expect(css).toContain('height: 0px'); - }); - - test('It grows to full height and 0 width in first 20%', () => { - - const css = internals.response.css(0.2, 0.8); - expect(css).toContain('width: 0px'); - expect(css).toContain('height: 200px'); - }); - - test('It expands to full height by the end', () => { - - const css = internals.response.css(1, 0); - expect(css).toContain('width: 100px'); - expect(css).toContain('height: 200px'); - }); - - test('It keeps element vertically centered by adjusting the margin', () => { - - const css = internals.response.css(0.1, 0.9); - expect(css).toContain('margin: 50px 50px'); - expect(css).toContain('height: 100px'); - }); - - test('It keeps element horizontally centered by adjusting the margin', () => { - - const css = internals.response.css(0.6, 0.4); - expect(css).toContain('margin: 0px 25px'); - expect(css).toContain('width: 50px'); - }); - }); + test('it has a default delay of 0ms', () => { + const response = blink(document.createElement('div'), {}); + + expect(response.delay).toBe(0); + }); + + test('it allows delay to be overridden', () => { + const response = blink(document.createElement('div'), { + delay: 300 + }); + + expect(response.delay).toBe(300); + }); + + test('it has a default duration of 400ms', () => { + const response = blink(document.createElement('div'), {}); + + expect(response.duration).toBe(400); + }); + + test('it allows delay to be overridden', () => { + const response = blink(document.createElement('div'), { + duration: 999 + }); + + expect(response.duration).toBe(999); + }); + + test('it uses sineOut as the default easing function', () => { + const response = blink(document.createElement('div'), {}); + + expect(response.easing).toBe(sineOut); + }); + + test('it allows easing function to be overridden', () => { + const response = blink(document.createElement('div'), { + easing: () => 666 + }); + + expect(response.easing(0)).toBe(666); + }); + + describe('css animation function', () => { + beforeEach(() => { + const div = document.createElement('div'); + div.style.width = '100px'; + div.style.height = '200px'; + internals.response = blink(div, {}); + }); + + test('It starts with with zeroed width and height', () => { + const css = internals.response.css(0, 1); + expect(css).toContain('width: 0px'); + expect(css).toContain('height: 0px'); + }); + + test('It grows to full height and 0 width in first 20%', () => { + const css = internals.response.css(0.2, 0.8); + expect(css).toContain('width: 0px'); + expect(css).toContain('height: 200px'); + }); + + test('It expands to full height by the end', () => { + const css = internals.response.css(1, 0); + expect(css).toContain('width: 100px'); + expect(css).toContain('height: 200px'); + }); + + test('It keeps element vertically centered by adjusting the margin', () => { + const css = internals.response.css(0.1, 0.9); + expect(css).toContain('margin: 50px 50px'); + expect(css).toContain('height: 100px'); + }); + + test('It keeps element horizontally centered by adjusting the margin', () => { + const css = internals.response.css(0.6, 0.4); + expect(css).toContain('margin: 0px 25px'); + expect(css).toContain('width: 50px'); + }); + }); }); diff --git a/src/lib/animations/blink.ts b/src/lib/animations/blink.ts index c291b06..623489a 100644 --- a/src/lib/animations/blink.ts +++ b/src/lib/animations/blink.ts @@ -1,25 +1,23 @@ import { sineOut } from 'svelte/easing'; import type { AnimationConfig } from 'svelte/animate'; -export const blink = function blink(node: HTMLElement, params: AnimationConfig): AnimationConfig{ +export const blink = function blink(node: HTMLElement, params: AnimationConfig): AnimationConfig { + const originalWidth = parseFloat(getComputedStyle(node).width); + const originalHeight = parseFloat(getComputedStyle(node).height); - const originalWidth = parseFloat(getComputedStyle(node).width); - const originalHeight = parseFloat(getComputedStyle(node).height); + return { + delay: params.delay || 0, + duration: params.duration || 400, + easing: params.easing || sineOut, + css: (t: number): string => { + const halfWidth = originalWidth / 2; + const halfHeight = originalHeight / 2; + const height = Math.round(t <= 0.2 ? (originalHeight * t) / 0.2 : originalHeight); + const marginY = Math.round(t <= 0.2 ? halfHeight * (1 - t / 0.2) : 0); + const width = Math.round(t > 0.2 ? ((t - 0.2) / 0.8) * originalWidth : 0); + const marginX = Math.round(t > 0.2 ? (1 - (t - 0.2) / 0.8) * halfWidth : halfWidth); - return { - delay: params.delay || 0, - duration: params.duration || 400, - easing: params.easing || sineOut, - css: (t: number): string => { - - const halfWidth = originalWidth / 2; - const halfHeight = originalHeight / 2; - const height = Math.round(t <= 0.2 ? (originalHeight * t) / 0.2 : originalHeight); - const marginY = Math.round(t <= 0.2 ? halfHeight * (1 - t / 0.2) : 0); - const width = Math.round(t > 0.2 ? ((t - 0.2) / 0.8) * originalWidth : 0); - const marginX = Math.round(t > 0.2 ? (1 - (t - 0.2) / 0.8) * halfWidth : halfWidth); - - return `width: ${width}px; height: ${height}px; margin: ${marginY}px ${marginX}px`; - } - }; + return `width: ${width}px; height: ${height}px; margin: ${marginY}px ${marginX}px`; + } + }; }; diff --git a/src/lib/components/actions/topic.svelte b/src/lib/components/actions/topic.svelte index 1311d06..a3cba3b 100644 --- a/src/lib/components/actions/topic.svelte +++ b/src/lib/components/actions/topic.svelte @@ -1,14 +1,14 @@
  • - - {@html $_('header.action.reply.display')} - + + {@html $_('header.action.reply.display')} +