diff --git a/.github/workflows/ci_workflow.yml b/.github/workflows/ci_workflow.yml
index 53b3d398c..69c652d5a 100644
--- a/.github/workflows/ci_workflow.yml
+++ b/.github/workflows/ci_workflow.yml
@@ -32,14 +32,14 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
- node-version: [18.19, 20.13]
+ node-version: [18.19, 20.13, 22.x]
outputs:
sha: ${{ steps.get-sha.outputs.SHA }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
@@ -57,7 +57,7 @@ jobs:
echo "SHA: ${{ steps.get-sha.outputs.SHA }}"
- name: Set up node ${{ matrix.node-version}}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # ratchet:actions/setup-node@v4.0.2
+ uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: ${{ matrix.node-version }}
@@ -65,7 +65,7 @@ jobs:
run: corepack enable
- name: Get yarn cache ${{ matrix.node-version}}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # ratchet:actions/setup-node@v4.0.2
+ uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
cache: 'yarn'
@@ -109,7 +109,7 @@ jobs:
- name: Upload build artifacts (main && develop)
# upload build artifacts for current node version and main or develop branch only
if: matrix.node-version == 20.13 && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # ratchet:actions/upload-artifact@v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # ratchet:actions/upload-artifact@v4.3.6
with:
name: dist
path: ${{ github.workspace }}/${{ env.DIST_DIR }}
@@ -136,7 +136,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
@@ -149,7 +149,7 @@ jobs:
path: ${{ env.DEV_GH_PAGES_DIR }}
- name: Download build artifacts
- uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # ratchet:actions/upload-artifact@v4.1.7
+ uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # ratchet:actions/upload-artifact@v4.1.8
with:
name: dist
path: ${{ github.workspace }}/${{ env.DIST_DIR }}
@@ -208,14 +208,14 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up node ${{ matrix.node-version}}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
@@ -248,7 +248,7 @@ jobs:
node-version: [20.13]
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
@@ -258,7 +258,7 @@ jobs:
- name: Create Release
id: create_release
if: ${{ success() && startsWith(github.ref, 'refs/tags/') }}
- uses: softprops/action-gh-release@a74c6b72af54cfa997e81df42d94703d6313a2d0 # v2.0.6
+ uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_VERSION: ${{ steps.get_version.outputs.VERSION }}
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index ee77a3664..40da09c11 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -26,7 +26,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
@@ -36,13 +36,13 @@ jobs:
fetch-depth: 2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
+ uses: github/codeql-action/init@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2
with:
languages: ${{ matrix.language }}
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
+ uses: github/codeql-action/autobuild@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
+ uses: github/codeql-action/analyze@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2
with:
category: '/language:${{matrix.language}}'
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index 1792f0181..bf2dcfbae 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- name: 'Checkout Repository'
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: 'Dependency Review'
- uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # v4.3.3
+ uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index ae73940b6..b6da2ca47 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -31,7 +31,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
@@ -41,7 +41,7 @@ jobs:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
+ uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with:
results_file: results.sarif
results_format: sarif
@@ -63,7 +63,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: SARIF file
path: results.sarif
@@ -71,6 +71,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
+ uses: github/codeql-action/upload-sarif@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2
with:
sarif_file: results.sarif
diff --git a/.github/workflows/visualize-repo.yml b/.github/workflows/visualize-repo.yml
index a5c441696..0c71b6f2d 100644
--- a/.github/workflows/visualize-repo.yml
+++ b/.github/workflows/visualize-repo.yml
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
+ uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
diff --git a/.husky/commit-msg b/.husky/commit-msg
index b6c171501..04b13f458 100755
--- a/.husky/commit-msg
+++ b/.husky/commit-msg
@@ -1,5 +1,2 @@
-#!/bin/sh
-. "$(dirname "$0")/_/husky.sh"
-
# cf. https://typicode.github.io/husky/#/?id=husky_git_params-ie-commitlint-
yarn commitlint --edit "$1"
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 8b393a899..1860b2afb 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,5 +1,2 @@
-#!/bin/sh
-. "$(dirname "$0")/_/husky.sh"
-
# cf. https://typicode.github.io/husky/#/?id=package-scripts
yarn run lint-staged
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d19937034..130f3be8a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,217 @@
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
+## [0.14.0](https://github.com/webern-unibas-ch/awg-app/compare/v0.12.3...v0.14.0) (2024-08-19)
+
+### Note
+
+Version 0.13.0 was intentionally skipped in honor of Arnold Schönberg, Anton Webern's lifelong teacher and friend, who feared the number 13 ([Triskaidekaphobia](https://en.wikipedia.org/wiki/Triskaidekaphobia)).
+
+### Features
+
+- **assets:** add corrections in Op12: EH + F ([8b42d86](https://github.com/webern-unibas-ch/awg-app/commit/8b42d864944d259b48fd649d906cf9c078d27540); thanks to [@masthom](https://github.com/masthom))
+- **assets:** add files for m36 ([5e2ffe6](https://github.com/webern-unibas-ch/awg-app/commit/5e2ffe64f3392efe6f3ad53930c5c9e6182203f2); thanks to [@chael-mi](https://github.com/chael-mi))
+- **assets:** add files for m38 ([03a6c17](https://github.com/webern-unibas-ch/awg-app/commit/03a6c17fd9dca14ecfa86be24b9c713b2ebe3afe); thanks to [@chael-mi](https://github.com/chael-mi))
+- **assets:** add preface content ([3a0210c](https://github.com/webern-unibas-ch/awg-app/commit/3a0210c26559265a63565c5eddda0be46e99ae6a); thanks to [@masthom](https://github.com/masthom))
+- **assets:** move complexes to separate assets file ([fe5571f](https://github.com/webern-unibas-ch/awg-app/commit/fe5571fa47ae820cbc326478e49d401cd091b309))
+- **assets:** move outline to separate assets file ([1e8997d](https://github.com/webern-unibas-ch/awg-app/commit/1e8997d3850e3af4056d369d573166bcef606d1b))
+- **core:** add EditionComplexes service ([c83edf3](https://github.com/webern-unibas-ch/awg-app/commit/c83edf3bf7e0057f8f6bab6f45f56a27b107a639))
+- **core:** add EditionOutline service ([7972875](https://github.com/webern-unibas-ch/awg-app/commit/7972875134ac3adb8a9bae642d548da1aefe2538))
+- **edition:** activate edition complex M 36 ([311b0b4](https://github.com/webern-unibas-ch/awg-app/commit/311b0b4c767ce56add9dd280a2cab81df787d94e))
+- **edition:** activate edition complex M 38 ([5b2a9bf](https://github.com/webern-unibas-ch/awg-app/commit/5b2a9bf6896e1d5c794678cdb685a0467a3e75d7))
+- **edition:** activate preface in app ([4213ea6](https://github.com/webern-unibas-ch/awg-app/commit/4213ea6358706c3443bdddcd3813a2c02bfd42a9))
+- **edition:** add initService & activate EditionOutline service in app ([2eb12d2](https://github.com/webern-unibas-ch/awg-app/commit/2eb12d230bfa4bcb13dfe4761431eead414816f9))
+- **edition:** add option to place folio items next to systems ([06ed541](https://github.com/webern-unibas-ch/awg-app/commit/06ed541e9ca5b3faf2d4930c667bdfccd01ea29f))
+- **edition:** add preface component and methods ([d4af6e8](https://github.com/webern-unibas-ch/awg-app/commit/d4af6e8b40e609759b971e85adcedde199e6fcb4))
+- **edition:** add ScrollToTop button to edition view ([3c75bbd](https://github.com/webern-unibas-ch/awg-app/commit/3c75bbd984ff032c2308e661733d80e8d26628e3))
+- **edition:** add textcritical comment blocks with headers ([7cf3a9b](https://github.com/webern-unibas-ch/awg-app/commit/7cf3a9b3b81247a730588fa0260ede4fdaeaa334))
+- **shared:** add ErrorAlertComponent ([dfbf6ce](https://github.com/webern-unibas-ch/awg-app/commit/dfbf6ce3bd96f35085ec8518560c70761426e650))
+
+### Bug Fixes
+
+- **app:** fix import paths ([8183d6f](https://github.com/webern-unibas-ch/awg-app/commit/8183d6fc2d276cc856586b585def2a7fcd3b251a))
+- **assets:** add missing colons ([3a256a4](https://github.com/webern-unibas-ch/awg-app/commit/3a256a407391c421025fe2e908f5088ef3bc6f44))
+- **assets:** add missing data files and placeholders for m36 ([feca45b](https://github.com/webern-unibas-ch/awg-app/commit/feca45baf7a028d1017269e91c23297c3900d7ab))
+- **assets:** add missing data files and placeholders for m38 ([62f0ad2](https://github.com/webern-unibas-ch/awg-app/commit/62f0ad297e6227a1034525fe500b094859333945))
+- **assets:** add missing italics ([67c1120](https://github.com/webern-unibas-ch/awg-app/commit/67c1120d932d4340ef5fe414fa05e55cda6fefd1))
+- **assets:** add missing M to source list in m36 ([5aab381](https://github.com/webern-unibas-ch/awg-app/commit/5aab38148620c79fe40158f63f968e6966116c2a))
+- **assets:** adjust corrections op12 to new block style ([8512841](https://github.com/webern-unibas-ch/awg-app/commit/851284112feb80d5327c9d37aba806e84db470f8))
+- **assets:** fix addendum for source E in op25 ([3621bd1](https://github.com/webern-unibas-ch/awg-app/commit/3621bd158e749bb825953d5faca38d029796a9fc); thanks to [@masthom](https://github.com/masthom))
+- **assets:** fix link boxes and textcritics for m36 ([153811c](https://github.com/webern-unibas-ch/awg-app/commit/153811c6fe4bd91d24aac454f26c64c355768df3))
+- **assets:** fix link boxes and textcritics for m38 ([d4fd615](https://github.com/webern-unibas-ch/awg-app/commit/d4fd61555cf856bd335ab2e076a1c26957716f3e))
+- **assets:** fix M number of M 135 ([97fbf07](https://github.com/webern-unibas-ch/awg-app/commit/97fbf07fe93f52de1bc954082f9ebc85753272d1))
+- **assets:** fix order of sources in op. 4 ([d4b9538](https://github.com/webern-unibas-ch/awg-app/commit/d4b95388c0e414c90a4cc55134eea509c3710095))
+- **assets:** fix source lists for m36 and m38 ([4ea7ddf](https://github.com/webern-unibas-ch/awg-app/commit/4ea7ddf3f554e8dfbf24553183271c0ed7b3a0b5))
+- **assets:** fix textcritics for m36 ([a1c2d20](https://github.com/webern-unibas-ch/awg-app/commit/a1c2d2044f96b3ca4a0cdeadd46e224b604581a6))
+- **assets:** fix typo in op25 ([463683d](https://github.com/webern-unibas-ch/awg-app/commit/463683d20c479fd54c2f0b90200e90510f2e554d))
+- **assets:** fix typos and missing infos ([b93a4a4](https://github.com/webern-unibas-ch/awg-app/commit/b93a4a450639ea76b94e541336a3c4dbf60c87b9))
+- **assets:** fix whitespace in intro op12 ([f01c916](https://github.com/webern-unibas-ch/awg-app/commit/f01c9169bad4f2ed89bf3c373efc103bd86f466a))
+- **assets:** optimize svgs for m36 with SVGO ([a747bf0](https://github.com/webern-unibas-ch/awg-app/commit/a747bf0b12ed636364a0c4871594296f3a10700b))
+- **assets:** optimize svgs for m38 with SVGO ([ed6bca2](https://github.com/webern-unibas-ch/awg-app/commit/ed6bca244947d1024d26db986e4fe1767b659630))
+- **assets:** remove doc file ([1773fe8](https://github.com/webern-unibas-ch/awg-app/commit/1773fe8cd6f563108125613aed5104a1d33bf89a))
+- **assets:** remove parentheses from C & D in op. 23 ([5eb4d0d](https://github.com/webern-unibas-ch/awg-app/commit/5eb4d0deceaa3e0994172e1f576e6ab9898ffd8b))
+- **assets:** remove Textfassung for m39 from source list ([f882bf7](https://github.com/webern-unibas-ch/awg-app/commit/f882bf73655dbbe0d1a3ce755fe30c79bbfdee71))
+- **assets:** rename files for m38 ([745abcb](https://github.com/webern-unibas-ch/awg-app/commit/745abcb546f47bf4f424cd924719e26d6a0b2bde))
+- **assets:** update contained M numbers in m34–m38 ([9ffa781](https://github.com/webern-unibas-ch/awg-app/commit/9ffa7815a90e722f1049bd69b638bcae6a4192ba))
+- **assets:** update folio convolute for m36 ([46fa626](https://github.com/webern-unibas-ch/awg-app/commit/46fa626701ece99966f98f9d0d26526c28ba2efa))
+- **assets:** update folio convolute for m38 ([1de1aa5](https://github.com/webern-unibas-ch/awg-app/commit/1de1aa59416a795bc1c3dbb219782174162dc442))
+- **assets:** update m22 ([51e0cf0](https://github.com/webern-unibas-ch/awg-app/commit/51e0cf04c045b769a79091b313ccb72be915aee8))
+- **assets:** update m34 ([a42d5bd](https://github.com/webern-unibas-ch/awg-app/commit/a42d5bd8e97122d3b06f8ef1876233215a0d219b))
+- **assets:** update m35_42 ([c99842a](https://github.com/webern-unibas-ch/awg-app/commit/c99842a894201d284ea505e51069a1d01ae27147))
+- **assets:** update m37 ([e318db3](https://github.com/webern-unibas-ch/awg-app/commit/e318db3923c1cde37d4c496d44e016be26a5f814))
+- **assets:** update source description for m36 ([8543e91](https://github.com/webern-unibas-ch/awg-app/commit/8543e91d771eec2d7400de253cd77bae2972f115))
+- **assets:** update source description for m38 ([e2530cf](https://github.com/webern-unibas-ch/awg-app/commit/e2530cf4aad675599d9c58247285042edef54be1))
+- **assets:** use angular white space instead of nbsp ([6fc51e6](https://github.com/webern-unibas-ch/awg-app/commit/6fc51e692de2e4238fbca680b14c4f359c79c241))
+- **assets:** use correct syntax for missing sources in op3 and op4 ([168c9e1](https://github.com/webern-unibas-ch/awg-app/commit/168c9e1db63aa01a8a3f3dafa25a4063cc3f3f95))
+- **core:** remove unused var and method from navbar ([490937c](https://github.com/webern-unibas-ch/awg-app/commit/490937c27d5ace98a07b30aae85c32f870beb4ec))
+- **edition:** activate EditionComplexes service in app ([b9200f0](https://github.com/webern-unibas-ch/awg-app/commit/b9200f095b224cbf3b518c3b94f3111bcb001756))
+- **edition:** add missing glyphs ([e261a31](https://github.com/webern-unibas-ch/awg-app/commit/e261a3141277638cce185c93293f1c64964c9203))
+- **edition:** add pedal to glyphs ([e4880c9](https://github.com/webern-unibas-ch/awg-app/commit/e4880c9a0aa46342e9ce76aa3bea3d0f2af7f44d))
+- **edition:** auto-generate message for empty textcritics ([b18f999](https://github.com/webern-unibas-ch/awg-app/commit/b18f999f6d4e4615e8596b9b44779debd4290a8f))
+- **edition:** clean up code ([2c8d513](https://github.com/webern-unibas-ch/awg-app/commit/2c8d5132d884b0e9c8e0e9109cafbede7027e003))
+- **edition:** fix track-by indices for EditionSeries ([3aa2da3](https://github.com/webern-unibas-ch/awg-app/commit/3aa2da32f8ea6756749c3f3fd14ab49f8fa3c00d))
+- **edition:** remove deprecated data files ([d5fb3fe](https://github.com/webern-unibas-ch/awg-app/commit/d5fb3fedce24906cc02ff3887ad3c615e4a99996))
+- **edition:** remove landscape image from jumbotron ([79f2766](https://github.com/webern-unibas-ch/awg-app/commit/79f276604e278364804bb97389bf536747aa81cd))
+- **edition:** remove unused edition type component ([0459b53](https://github.com/webern-unibas-ch/awg-app/commit/0459b53aad604a6ce91182d7ff4294540f4e504c))
+- **edition:** remove unused method from edition service ([6e7b8dc](https://github.com/webern-unibas-ch/awg-app/commit/6e7b8dca332d0a64ae9db40f4b9f44b87716bfc8))
+- **edition:** remove unused type from complex model ([c8b1882](https://github.com/webern-unibas-ch/awg-app/commit/c8b1882423fb6adc137fadfc4980817b053308b7))
+- **edition:** simplify handling of sources in SourceList ([9c34a77](https://github.com/webern-unibas-ch/awg-app/commit/9c34a77562b8456601baac1dd57044c076c5d3c4))
+- **edition:** use correct constant for AWG III/5 ([d6b52a7](https://github.com/webern-unibas-ch/awg-app/commit/d6b52a7e8ce9e93449cd5026df69bdceb1815e14))
+- **edition:** use jumbotron for complex titles ([4f47a9a](https://github.com/webern-unibas-ch/awg-app/commit/4f47a9a2395d516927563284bb11c50662d2be34))
+- **edition:** use loading spinner for all edition views ([1c2135e](https://github.com/webern-unibas-ch/awg-app/commit/1c2135e0a5646c6256ca06a538e9bd47f87b0865))
+- **edition:** use shared ErrorAlertComponent ([e230c68](https://github.com/webern-unibas-ch/awg-app/commit/e230c6834590bb249f6a17796145304185fc7283))
+
+### Code Refactoring
+
+- **assets:** use blocks for textcritics ([77e50a1](https://github.com/webern-unibas-ch/awg-app/commit/77e50a1c9ebf127125a5c83b7539562442f9ae03))
+- **assets:** use complex id as object key in JSON structure ([6216c48](https://github.com/webern-unibas-ch/awg-app/commit/6216c48ca4bb4acb01ca999cbf78543ab42637f8))
+- **core:** rename EditionComplexes service folder ([21994a5](https://github.com/webern-unibas-ch/awg-app/commit/21994a52a7fbfa717ea88d10de5652107e2f6b2f))
+- **edition:** move complex creation logic from data to model ([66e9613](https://github.com/webern-unibas-ch/awg-app/commit/66e9613c0b6695d4fddf1fbd5ae071324f096b0b))
+- **edition:** move series and section into pubStatement ([172a729](https://github.com/webern-unibas-ch/awg-app/commit/172a729cce9335cd5c9688226eb2b6c1b27e8736))
+- **edition:** rename class for intro paragraph ([fa99e4f](https://github.com/webern-unibas-ch/awg-app/commit/fa99e4f24af196137a4e54f1642f43506025e9b8))
+- **edition:** rename complex json data model ([b58a0d4](https://github.com/webern-unibas-ch/awg-app/commit/b58a0d403ea32c2bf1c9b4133108a2842436a84a))
+- **edition:** rename edition complex subclasses ([0e6bc38](https://github.com/webern-unibas-ch/awg-app/commit/0e6bc38144b7f2f54f3e5d63da800d1d88849d4a))
+- **edition:** rename edition related service and comp methods ([ac1b098](https://github.com/webern-unibas-ch/awg-app/commit/ac1b09815453ee0a83a901bde657082c2a02e47d))
+- **edition:** rename method for EditionView setup ([d0d4094](https://github.com/webern-unibas-ch/awg-app/commit/d0d40948dc3a1a2833426a419d63bb507d87f07b))
+- **edition:** rename parts of edition outline model ([308b8ae](https://github.com/webern-unibas-ch/awg-app/commit/308b8ae6ee7cf94d3d5ebdda64d0c13a3d840b1f))
+- **edition:** rename respStatment ([242c934](https://github.com/webern-unibas-ch/awg-app/commit/242c934272fa6a70584c1124f2cd3cdcb6b59a74))
+- **edition:** simplify and fully test GraphVisualizerService ([dce9676](https://github.com/webern-unibas-ch/awg-app/commit/dce967666dadedf9053da2a92232326cd15e0415))
+- **edition:** simplify generation of edition breadcrumb ([d9d9a5d](https://github.com/webern-unibas-ch/awg-app/commit/d9d9a5d9bb0fd4d081e1d5b482ad4ae1b30d0fd4))
+- **edition:** sort methods in editionDataService ([c7b048d](https://github.com/webern-unibas-ch/awg-app/commit/c7b048d69c7d6a23204a224eff4cb8bbd55614b2))
+
+### Tests
+
+- **app:** fix syntax of remaining tests ([e057b49](https://github.com/webern-unibas-ch/awg-app/commit/e057b4912a9f1b2da3d80d495f5913e5b6f0b3de))
+- **app:** fix syntax of some more tests ([25c395b](https://github.com/webern-unibas-ch/awg-app/commit/25c395be97b219dbe338dc3fd44342706959945b))
+- **app:** fix tests after changes ([11ff7ab](https://github.com/webern-unibas-ch/awg-app/commit/11ff7aba433d82986100ec9f318aa8f562576ffa))
+- **app:** fix tests for AppComponent ([52d7a6a](https://github.com/webern-unibas-ch/awg-app/commit/52d7a6a394f66dbf259216f916bce2e897c12d7a))
+- **app:** fix typos and order in some tests ([9355e33](https://github.com/webern-unibas-ch/awg-app/commit/9355e33b7d7876b3aeb502885a600cb3de1ac1c2))
+- **app:** fix updated models and services in tests ([6f78602](https://github.com/webern-unibas-ch/awg-app/commit/6f78602e402b021e403aa3bfec4ee6aadae9761b))
+- **edition:** add more tests for edition sheets ([7308d6f](https://github.com/webern-unibas-ch/awg-app/commit/7308d6fa4c83153770830fab7f8029be2d7e6cb2))
+- **edition:** add tests for EditionSectionsComponent ([d626e57](https://github.com/webern-unibas-ch/awg-app/commit/d626e57468f57e38c1d1ff32c8c622aafbc2ee86))
+- **edition:** add tests for preface service methods ([b3efad1](https://github.com/webern-unibas-ch/awg-app/commit/b3efad199fc456f30e832068fc21885aa4676792))
+- **edition:** fix incorrect awg constant ([f8b8291](https://github.com/webern-unibas-ch/awg-app/commit/f8b829149b57c962f39e448d5c52b0e8a43fc5f8))
+- **edition:** fix intro paragraph class after change ([b2e99b4](https://github.com/webern-unibas-ch/awg-app/commit/b2e99b4d012ec00419d9f479605fb1d193e8d4da))
+- **edition:** fix tests after changes ([89abcbb](https://github.com/webern-unibas-ch/awg-app/commit/89abcbb6aa09db60f63d050228e1b21ff9cfdb7e))
+- **edition:** fix tests after changes ([d0e738e](https://github.com/webern-unibas-ch/awg-app/commit/d0e738eec6de46dce044a77d9ca79e385adab414))
+- **edition:** fix tests for EditionComplexes service ([40a3d93](https://github.com/webern-unibas-ch/awg-app/commit/40a3d93c569c91184fa78d43451551ef86f9024e))
+- **edition:** fix tests for textcritical comment blocks ([d419ae9](https://github.com/webern-unibas-ch/awg-app/commit/d419ae98767196007a90db6b5a66c397ee4e490c))
+- **edition:** remove focus from test ([12c6551](https://github.com/webern-unibas-ch/awg-app/commit/12c6551d6ed5c8e5c8d40b9659eb2b8021d7b12c))
+- **edition:** use regular edition outline in EditionView test ([97b5926](https://github.com/webern-unibas-ch/awg-app/commit/97b592625c7f14a71d748ef20d5110aed8bfd77b))
+
+### Continuous Integration
+
+- **gh-actions:** include node 22 in workflow ([2684667](https://github.com/webern-unibas-ch/awg-app/commit/2684667984427ab9a3b4bead1da4e317d1381ecd))
+- **gh-actions:** pin fixed node version temporarily ([eb8e8c5](https://github.com/webern-unibas-ch/awg-app/commit/eb8e8c56a1e899c764c010f0cd0a76965ab0c763))
+- **gh-actions:** switch back to latest node v22 ([19a196d](https://github.com/webern-unibas-ch/awg-app/commit/19a196d3375956ee79e07c66ed3f47b8d017f02c))
+
+### Documentation
+
+- **edition:** add JSDocs to new SourceDescription sub-classes ([bfd6360](https://github.com/webern-unibas-ch/awg-app/commit/bfd636080a97e7252cfbd08b41c925c8bb7768ad))
+
+### Styles
+
+- **edition:** use shadow for cards ([2c4dad6](https://github.com/webern-unibas-ch/awg-app/commit/2c4dad6e35dbab8f9c2c635f2f8d6fa2769505b6))
+- **search:** fix error class ([a424df0](https://github.com/webern-unibas-ch/awg-app/commit/a424df0c4c6f6ae34d08a8a1306e34f34222a519))
+
+### Build System
+
+- **deps-dev:** bump @commitlint/cli in the commitlint group ([8eadc48](https://github.com/webern-unibas-ch/awg-app/commit/8eadc4816d9af96fc6b1feae5a51e90147c99060))
+- **deps-dev:** bump @types/node from 18.19.39 to 18.19.40 ([88a8559](https://github.com/webern-unibas-ch/awg-app/commit/88a8559e07401fb362eb65db9017028ff81faa75))
+- **deps-dev:** bump @types/node from 18.19.40 to 18.19.41 ([7b2b8fe](https://github.com/webern-unibas-ch/awg-app/commit/7b2b8fe47d4335a178f2109397c8777c7260b244))
+- **deps-dev:** bump @types/node from 18.19.41 to 18.19.42 ([ef03a45](https://github.com/webern-unibas-ch/awg-app/commit/ef03a45bd47943ccaa0517d74bf1fe926347cd52))
+- **deps-dev:** bump @types/node from 18.19.42 to 20.14.14 ([a7a517e](https://github.com/webern-unibas-ch/awg-app/commit/a7a517e6a1fe9b957ad9df5aace977bb6772af8b))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.10.2 to 48.11.0 ([ba58324](https://github.com/webern-unibas-ch/awg-app/commit/ba583245841157874a353fe551302ed6c42133ed))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.11.0 to 50.0.0 ([13d1071](https://github.com/webern-unibas-ch/awg-app/commit/13d107130553229a51c3a878eeb3e2d1fd005d27))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.5.0 to 48.5.2 ([be1bd20](https://github.com/webern-unibas-ch/awg-app/commit/be1bd209680d2cbb96b5efee71c0ada2414daf5c))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.5.2 to 48.6.0 ([47d0c31](https://github.com/webern-unibas-ch/awg-app/commit/47d0c31a88d2f0986920f86325bab2a7d7875c66))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.6.0 to 48.7.0 ([ddcf59a](https://github.com/webern-unibas-ch/awg-app/commit/ddcf59a419bf5f9348d2339aa578ff3652fe132b))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.7.0 to 48.8.3 ([cec7fed](https://github.com/webern-unibas-ch/awg-app/commit/cec7fedba402c4259693a386dfc9aa92c8bc7f92))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.8.3 to 48.9.2 ([490d1ff](https://github.com/webern-unibas-ch/awg-app/commit/490d1ffaa39523330d2b24b0c0d85e97fd82b752))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.9.2 to 48.10.2 ([53d904b](https://github.com/webern-unibas-ch/awg-app/commit/53d904b13aa33513e73827c8b59f8b4170b03d9f))
+- **deps-dev:** bump eslint-plugin-jsdoc from 50.0.0 to 50.0.1 ([4069d81](https://github.com/webern-unibas-ch/awg-app/commit/4069d81491763d30c06ac52426293e2175c3b187))
+- **deps-dev:** bump eslint-plugin-jsdoc from 50.0.1 to 50.2.1 ([e399969](https://github.com/webern-unibas-ch/awg-app/commit/e399969a0b184c4958c81eb3c3f9a933eface7bb))
+- **deps-dev:** bump eslint-plugin-jsdoc from 50.2.1 to 50.2.2 ([09fabda](https://github.com/webern-unibas-ch/awg-app/commit/09fabda42f6c81e099e5d72eb6bf27027b5ac819))
+- **deps-dev:** bump eslint-plugin-prettier from 5.1.3 to 5.2.1 ([fb531b4](https://github.com/webern-unibas-ch/awg-app/commit/fb531b4d5b214ba1519db8d871c1076bc2ace6fa))
+- **deps-dev:** bump husky from 9.0.11 to 9.1.1 ([aa0566f](https://github.com/webern-unibas-ch/awg-app/commit/aa0566f3413d9bcf44014e2e581d80cf1e76fe35))
+- **deps-dev:** bump husky from 9.1.1 to 9.1.2 ([612f448](https://github.com/webern-unibas-ch/awg-app/commit/612f44860baed9c975d9126abaa2b07f2ca2f117))
+- **deps-dev:** bump husky from 9.1.2 to 9.1.4 ([baa3501](https://github.com/webern-unibas-ch/awg-app/commit/baa350151922dcd0048caba49b63518c0acb4628))
+- **deps-dev:** bump jasmine-core from 5.1.2 to 5.2.0 ([b903c1e](https://github.com/webern-unibas-ch/awg-app/commit/b903c1ee3c01f5c3c2cbaf3abac3c62ca028dac1))
+- **deps-dev:** bump karma from 6.4.3 to 6.4.4 ([3e9ba46](https://github.com/webern-unibas-ch/awg-app/commit/3e9ba4665182b8f58f4907a7192365e390894b78))
+- **deps-dev:** bump lint-staged from 15.2.7 to 15.2.8 ([f4513de](https://github.com/webern-unibas-ch/awg-app/commit/f4513de5d45e51b23531e9fff1c4fd69071e195d))
+- **deps-dev:** bump lint-staged from 15.2.8 to 15.2.9 ([32b44c2](https://github.com/webern-unibas-ch/awg-app/commit/32b44c2925c049cb857d19746613157fcb066e2f))
+- **deps-dev:** bump prettier from 3.3.2 to 3.3.3 ([bd8330c](https://github.com/webern-unibas-ch/awg-app/commit/bd8330c6d86c70b8f870fb39bcfb6035947ad3ee))
+- **deps-dev:** bump the angular-cli-devkit group with 2 updates ([2285f9b](https://github.com/webern-unibas-ch/awg-app/commit/2285f9bca446f055f8298ee8b3ef968d000e4703))
+- **deps-dev:** bump the angular-cli-devkit group with 2 updates ([9f4319d](https://github.com/webern-unibas-ch/awg-app/commit/9f4319d3e34e4f241ec37378842aac2b2a10bf74))
+- **deps-dev:** bump the angular-cli-devkit group with 2 updates ([61e438e](https://github.com/webern-unibas-ch/awg-app/commit/61e438e11e56547bc3c6ecff2066b891a36f37f2))
+- **deps-dev:** bump the angular-cli-devkit group with 2 updates ([f9fb819](https://github.com/webern-unibas-ch/awg-app/commit/f9fb819ff4f0eb2649848fe38dbd810f347ba0ab))
+- **deps-dev:** bump the angular-cli-devkit group with 2 updates ([46432b5](https://github.com/webern-unibas-ch/awg-app/commit/46432b509d1b77a50ab8289f246deafaebd5fa68))
+- **deps-dev:** bump the angular-cli-devkit group with 2 updates ([688da7e](https://github.com/webern-unibas-ch/awg-app/commit/688da7ec256c46472e4352c09c1f0d2ec491b19b))
+- **deps-dev:** bump the angular-cli-devkit group with 2 updates ([26fce92](https://github.com/webern-unibas-ch/awg-app/commit/26fce928e28d4f4a743231ec8aa96820c0656029))
+- **deps-dev:** bump the angular-eslint group with 5 updates ([5f37c41](https://github.com/webern-unibas-ch/awg-app/commit/5f37c419bdc27f33ec965931ab4a835e65ff710f))
+- **deps-dev:** bump the angular-eslint group with 5 updates ([73b4783](https://github.com/webern-unibas-ch/awg-app/commit/73b47838a8bf5ec447ad2dcdb6395f61f72eaebb))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([f58e89b](https://github.com/webern-unibas-ch/awg-app/commit/f58e89b794c8995cc5da10230bc79dae70df97b0))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([94a0151](https://github.com/webern-unibas-ch/awg-app/commit/94a01519fc1654e6b2a1e57ba526329dddacfefc))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([185e1d9](https://github.com/webern-unibas-ch/awg-app/commit/185e1d9dfa140ad0231991dd5cdd2bac1cbdd8bf))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([5db38a8](https://github.com/webern-unibas-ch/awg-app/commit/5db38a80fd5319ac749c19de91654b1eb59ac80a))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([4010d7a](https://github.com/webern-unibas-ch/awg-app/commit/4010d7a1a1451df6c8ef160e5e498caede477f79))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([6e2bf13](https://github.com/webern-unibas-ch/awg-app/commit/6e2bf13266eab01fc3f3ea2368922fbfa9150d93))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([edae3ff](https://github.com/webern-unibas-ch/awg-app/commit/edae3ffa154c44d705e8247021be6a3368db7763))
+- **deps-dev:** bump the typescript-eslint group with 2 updates ([00e701c](https://github.com/webern-unibas-ch/awg-app/commit/00e701c8ef6cad84734186b61906368c286cbb5e))
+- **deps-dev:** bump typescript from 5.5.2 to 5.5.4 ([e5dd837](https://github.com/webern-unibas-ch/awg-app/commit/e5dd83730a004b817c79ef258e45b34656e021f9))
+- **deps-dev:** update husky ([6e58c7c](https://github.com/webern-unibas-ch/awg-app/commit/6e58c7c0236087f2b31597c1090afe3adb2d0772))
+- **deps:** bump @codemirror/legacy-modes from 6.4.0 to 6.4.1 ([59cb709](https://github.com/webern-unibas-ch/awg-app/commit/59cb7097a6d263bcfa44f8ab629adeae28dc3dc5))
+- **deps:** bump @fortawesome/free-solid-svg-icons ([192df83](https://github.com/webern-unibas-ch/awg-app/commit/192df8366ff5b8b568aa928fd178ad5e09082026))
+- **deps:** bump actions/dependency-review-action from 4.3.3 to 4.3.4 ([9a2bd0c](https://github.com/webern-unibas-ch/awg-app/commit/9a2bd0cb11694ad87e4e15b1078329f14e9a8b85))
+- **deps:** bump actions/download-artifact from 4.1.7 to 4.1.8 ([003e5d0](https://github.com/webern-unibas-ch/awg-app/commit/003e5d0ddfb4d310904ecb086196d3e8c2954c7e))
+- **deps:** bump actions/setup-node from 4.0.2 to 4.0.3 ([5dc9a95](https://github.com/webern-unibas-ch/awg-app/commit/5dc9a95d047aabcf2013ff839714063391591e67))
+- **deps:** bump actions/upload-artifact from 4.3.3 to 4.3.4 ([1cd8e55](https://github.com/webern-unibas-ch/awg-app/commit/1cd8e555ea7727fde0d1f377291725d50cd36b55))
+- **deps:** bump actions/upload-artifact from 4.3.4 to 4.3.5 ([5c795e4](https://github.com/webern-unibas-ch/awg-app/commit/5c795e431fb0ef10a4ec7c3eea04ee6277460b6f))
+- **deps:** bump actions/upload-artifact from 4.3.5 to 4.3.6 ([7cc20df](https://github.com/webern-unibas-ch/awg-app/commit/7cc20df20411b3c04ab0b4e3c3791b58d59729d0))
+- **deps:** bump axios from 1.7.2 to 1.7.4 ([42e32d1](https://github.com/webern-unibas-ch/awg-app/commit/42e32d1154c4e1552eb1f61e26be37010e4889ec))
+- **deps:** bump github/codeql-action from 3.25.10 to 3.25.11 ([f135634](https://github.com/webern-unibas-ch/awg-app/commit/f13563420f6067da96618390d3d4573f0a338b53))
+- **deps:** bump github/codeql-action from 3.25.11 to 3.25.12 ([80de336](https://github.com/webern-unibas-ch/awg-app/commit/80de33633cb73937d73fa5e0e3573c4e86efc6ac))
+- **deps:** bump github/codeql-action from 3.25.12 to 3.25.13 ([cb03a00](https://github.com/webern-unibas-ch/awg-app/commit/cb03a00684d6c05ce4c86ed33e566a0bb46b59a0))
+- **deps:** bump github/codeql-action from 3.25.13 to 3.25.15 ([b053cf9](https://github.com/webern-unibas-ch/awg-app/commit/b053cf99ae1e7a0e427a415d51a713d93937c547))
+- **deps:** bump github/codeql-action from 3.25.15 to 3.26.0 ([3fa2067](https://github.com/webern-unibas-ch/awg-app/commit/3fa2067eb64ee807a0274cb4037cb6f4e41b6e96))
+- **deps:** bump github/codeql-action from 3.26.0 to 3.26.1 ([91455ad](https://github.com/webern-unibas-ch/awg-app/commit/91455adc853e67c8388b6ac12980d1eec284d5b2))
+- **deps:** bump github/codeql-action from 3.26.1 to 3.26.2 ([9a2c7ae](https://github.com/webern-unibas-ch/awg-app/commit/9a2c7aea2fe6c5cb67cf273c8b08e6badb6bcef4))
+- **deps:** bump n3 from 1.17.4 to 1.20.3 ([239a91f](https://github.com/webern-unibas-ch/awg-app/commit/239a91f390f55b5a0d199b36bd997360b044d05e))
+- **deps:** bump n3 from 1.20.3 to 1.20.4 ([965de9b](https://github.com/webern-unibas-ch/awg-app/commit/965de9bf734225a01e1b5443fef43fad77eedee3))
+- **deps:** bump ossf/scorecard-action from 2.3.3 to 2.4.0 ([0df58ee](https://github.com/webern-unibas-ch/awg-app/commit/0df58eed5b81397548e075631f87eb58ccb26d5f))
+- **deps:** bump softprops/action-gh-release from 2.0.6 to 2.0.8 ([86c7296](https://github.com/webern-unibas-ch/awg-app/commit/86c729603f101fdd5ddfecf86f5afbd770a7e409))
+- **deps:** bump step-security/harden-runner from 2.8.1 to 2.9.0 ([4fce8a7](https://github.com/webern-unibas-ch/awg-app/commit/4fce8a709e9f4b2fe2238589f01ce2f4e453cc0a))
+- **deps:** bump step-security/harden-runner from 2.9.0 to 2.9.1 ([1df7522](https://github.com/webern-unibas-ch/awg-app/commit/1df75228c0d65864d817719368bfcc6e605e6e6a))
+- **deps:** bump the angular group with 11 updates ([986c124](https://github.com/webern-unibas-ch/awg-app/commit/986c124c9ed37fa626e43f7d8b81c5ce7d14727c))
+- **deps:** bump the angular group with 11 updates ([cb33669](https://github.com/webern-unibas-ch/awg-app/commit/cb336690cc4195d4f840105565ecb0051f0c8c55))
+- **deps:** bump the angular group with 11 updates ([d8de582](https://github.com/webern-unibas-ch/awg-app/commit/d8de58266ba658348a715e43020adc17037c0aaf))
+- **deps:** bump the angular group with 11 updates ([2b8ec44](https://github.com/webern-unibas-ch/awg-app/commit/2b8ec44a161d9791776be8f041d13f20540d2a7f))
+- **deps:** bump the angular group with 11 updates ([e7589fe](https://github.com/webern-unibas-ch/awg-app/commit/e7589fe92525767d164a850f9a3be92c64806ba5))
+- **deps:** bump the angular group with 11 updates ([972d326](https://github.com/webern-unibas-ch/awg-app/commit/972d32656c33cfb5ed35e0edee30ac708053f2ff))
+- **deps:** bump the angular group with 11 updates ([a132ec2](https://github.com/webern-unibas-ch/awg-app/commit/a132ec2951c9fd8710f731eabb387003cb19f3f9))
+- **deps:** bump zone.js from 0.14.7 to 0.14.8 ([ef54a7d](https://github.com/webern-unibas-ch/awg-app/commit/ef54a7dc4c986b3fab6382de55ac70b4a8198f32))
+- **deps:** bump zone.js from 0.14.8 to 0.14.10 ([dc5f651](https://github.com/webern-unibas-ch/awg-app/commit/dc5f65162025246fef64775327b5c30f5ee3745d))
+
## [0.12.3](https://github.com/webern-unibas-ch/awg-app/compare/v0.12.2...v0.12.3) (2024-07-01)
### Features
diff --git a/package.json b/package.json
index 86684112d..0fd8c5749 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "awg-app",
- "version": "0.12.3",
+ "version": "0.14.0",
"license": "MIT",
"author": {
"name": "Stefan Münnich",
@@ -84,19 +84,19 @@
"deploy:ci": "ng deploy --no-build --message=\"Release $npm_package_name (v$npm_package_version) on gh-pages\""
},
"dependencies": {
- "@angular/animations": "^18.0.5",
- "@angular/common": "^18.0.5",
- "@angular/compiler": "^18.0.5",
- "@angular/core": "^18.0.5",
- "@angular/forms": "^18.0.5",
- "@angular/localize": "^18.0.5",
- "@angular/platform-browser": "^18.0.5",
- "@angular/platform-browser-dynamic": "^18.0.5",
- "@angular/platform-server": "^18.0.5",
- "@angular/router": "^18.0.5",
- "@codemirror/legacy-modes": "^6.4.0",
+ "@angular/animations": "^18.2.0",
+ "@angular/common": "^18.2.0",
+ "@angular/compiler": "^18.2.0",
+ "@angular/core": "^18.2.0",
+ "@angular/forms": "^18.2.0",
+ "@angular/localize": "^18.2.0",
+ "@angular/platform-browser": "^18.2.0",
+ "@angular/platform-browser-dynamic": "^18.2.0",
+ "@angular/platform-server": "^18.2.0",
+ "@angular/router": "^18.2.0",
+ "@codemirror/legacy-modes": "^6.4.1",
"@fortawesome/angular-fontawesome": "^0.15.0",
- "@fortawesome/free-solid-svg-icons": "^6.5.2",
+ "@fortawesome/free-solid-svg-icons": "^6.6.0",
"@kolkov/ngx-gallery": "2.0.1",
"@ng-bootstrap/ng-bootstrap": "^17.0.0",
"@popperjs/core": "^2.11.8",
@@ -109,31 +109,31 @@
"d3-zoom": "^3.0.0",
"font-awesome": "^4.7.0",
"json2typescript": "^1.5.1",
- "n3": "^1.17.4",
+ "n3": "^1.20.4",
"ngx-json-viewer": "^3.2.1",
"rdfstore": "musicenfanthen/rdfstore-js#v0.9.18-alpha.16",
"rxjs": "~7.8.1",
"stream": "^0.0.3",
"tslib": "^2.6.2",
- "zone.js": "~0.14.7"
+ "zone.js": "~0.14.10"
},
"devDependencies": {
- "@angular-devkit/build-angular": "^18.0.6",
- "@angular-eslint/builder": "^18.1.0",
- "@angular-eslint/eslint-plugin": "^18.1.0",
- "@angular-eslint/eslint-plugin-template": "^18.1.0",
- "@angular-eslint/schematics": "^18.1.0",
- "@angular-eslint/template-parser": "^18.1.0",
- "@angular/cli": "^18.0.6",
- "@angular/compiler-cli": "^18.0.5",
- "@commitlint/cli": "^19.3.0",
+ "@angular-devkit/build-angular": "^18.2.0",
+ "@angular-eslint/builder": "^18.3.0",
+ "@angular-eslint/eslint-plugin": "^18.3.0",
+ "@angular-eslint/eslint-plugin-template": "^18.3.0",
+ "@angular-eslint/schematics": "^18.3.0",
+ "@angular-eslint/template-parser": "^18.3.0",
+ "@angular/cli": "^18.2.0",
+ "@angular/compiler-cli": "^18.2.0",
+ "@commitlint/cli": "^19.4.0",
"@commitlint/config-angular": "^19.3.0",
"@compodoc/compodoc": "^1.1.25",
"@types/d3": "^7.4.3",
"@types/jasmine": "~5.1.4",
- "@types/node": "^18.19.39",
- "@typescript-eslint/eslint-plugin": "^7.14.1",
- "@typescript-eslint/parser": "^7.14.1",
+ "@types/node": "^20.14.14",
+ "@typescript-eslint/eslint-plugin": "^8.1.0",
+ "@typescript-eslint/parser": "^8.1.0",
"angular-cli-ghpages": "^2.0.1",
"commit-and-tag-version": "^12.4.1",
"conventional-recommended-bump": "^10.0.0",
@@ -142,20 +142,20 @@
"eslint-plugin-angular": "^4.1.0",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-plugin-import": "^2.29.1",
- "eslint-plugin-jsdoc": "^48.5.0",
- "eslint-plugin-prettier": "^5.1.3",
+ "eslint-plugin-jsdoc": "^50.2.2",
+ "eslint-plugin-prettier": "^5.2.1",
"gzipper": "^7.2.0",
- "husky": "^9.0.11",
- "jasmine-core": "~5.1.2",
- "karma": "~6.4.3",
+ "husky": "^9.1.4",
+ "jasmine-core": "~5.2.0",
+ "karma": "~6.4.4",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "^2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "^2.1.0",
- "lint-staged": "^15.2.7",
- "prettier": "^3.3.2",
+ "lint-staged": "^15.2.9",
+ "prettier": "^3.3.3",
"source-map-explorer": "^2.5.3",
- "typescript": "~5.5.2",
+ "typescript": "~5.5.4",
"webpack-bundle-analyzer": "^4.10.2"
},
"engines": {
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts
index ad958d703..fa9afc787 100644
--- a/src/app/app.component.spec.ts
+++ b/src/app/app.component.spec.ts
@@ -2,6 +2,7 @@
import { Location } from '@angular/common';
import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { Title } from '@angular/platform-browser';
import { Router, RouterModule, Routes } from '@angular/router';
import Spy = jasmine.Spy;
@@ -9,7 +10,7 @@ import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { expectSpyCall, expectToBe, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
-import { AnalyticsService } from '@awg-core/services';
+import { AnalyticsService, EditionInitService } from '@awg-core/services';
import { AppComponent } from './app.component';
@@ -30,9 +31,14 @@ export class RoutedTestMockComponent {}
export class RoutedTest2MockComponent {}
export const MOCK_ROUTES: Routes = [
- { path: '', redirectTo: 'test', pathMatch: 'full' },
- { path: 'test', component: RoutedTestMockComponent },
- { path: 'test2', component: RoutedTest2MockComponent },
+ { path: '', redirectTo: 'test1', pathMatch: 'full' },
+ { path: 'test1', component: RoutedTestMockComponent, data: { title: 'Custom Page Title 1' } },
+ {
+ path: 'test2',
+ component: RoutedTest2MockComponent,
+ data: {},
+ children: [{ path: 'test3', component: RoutedTestMockComponent, data: { title: 'Custom Page Title 3' } }],
+ },
];
describe('AppComponent (DONE)', () => {
@@ -40,12 +46,18 @@ describe('AppComponent (DONE)', () => {
let fixture: ComponentFixture;
let compDe: DebugElement;
- let router: Router;
let location: Location;
+ let router: Router;
+ let titleService: Title;
let mockAnalyticsService: Partial;
+ let mockEditionInitService: Partial;
+
+ let getTitleSpy: Spy;
+ let setTitleSpy: Spy;
let initialzeAnalyticsSpy: Spy;
let trackpageViewSpy: Spy;
+ let initializeEditionSpy: Spy;
beforeEach(waitForAsync(() => {
// Create a mocked AnalyticsService with an `initializeAnalytics` and `trackPageView` spy
@@ -58,6 +70,13 @@ describe('AppComponent (DONE)', () => {
},
};
+ // Create a mocked EditionInitService with an `initializeEdition` spy
+ mockEditionInitService = {
+ initializeEdition: (): void => {
+ // Intentional empty test override
+ },
+ };
+
TestBed.configureTestingModule({
imports: [RouterModule.forRoot(MOCK_ROUTES)],
declarations: [
@@ -68,11 +87,18 @@ describe('AppComponent (DONE)', () => {
RoutedTestMockComponent,
RoutedTest2MockComponent,
],
- providers: [{ provide: AnalyticsService, useValue: mockAnalyticsService }],
+ providers: [
+ { provide: AnalyticsService, useValue: mockAnalyticsService },
+ { provide: EditionInitService, useValue: mockEditionInitService },
+ Title,
+ ],
}).compileComponents();
// Spies for service methods
+ getTitleSpy = spyOn(Title.prototype, 'getTitle').and.returnValue('Default Page Title');
+ setTitleSpy = spyOn(Title.prototype, 'setTitle').and.callThrough();
initialzeAnalyticsSpy = spyOn(mockAnalyticsService, 'initializeAnalytics').and.callThrough();
+ initializeEditionSpy = spyOn(mockEditionInitService, 'initializeEdition').and.callThrough();
trackpageViewSpy = spyOn(mockAnalyticsService, 'trackPageView').and.callThrough();
}));
@@ -84,8 +110,9 @@ describe('AppComponent (DONE)', () => {
component = fixture.componentInstance;
compDe = fixture.debugElement;
- router = TestBed.inject(Router);
location = TestBed.inject(Location);
+ router = TestBed.inject(Router);
+ titleService = TestBed.inject(Title);
// Workaround for ngZone issue;
// Cf. https://github.com/angular/angular/issues/25837
@@ -109,9 +136,12 @@ describe('AppComponent (DONE)', () => {
expect(component).toBeTruthy();
}));
- it('... injected service should use provided mockValue', () => {
+ it('... injected services should use provided mockValues', () => {
const analyticsService = TestBed.inject(AnalyticsService);
- expect(analyticsService === mockAnalyticsService).toBe(true);
+ expectToBe(analyticsService === mockAnalyticsService, true);
+
+ const editionInitService = TestBed.inject(EditionInitService);
+ expectToBe(editionInitService === mockEditionInitService, true);
});
describe('router setup (self-test)', () => {
@@ -119,18 +149,18 @@ describe('AppComponent (DONE)', () => {
expectToBe(location.path(), '');
}));
- it("... should redirect to /test from '' redirect", waitForAsync(() => {
+ it("... should redirect to /test1 from '' redirect", waitForAsync(() => {
fixture.ngZone.run(() => {
router.navigate(['']).then(() => {
- expectToBe(location.path(), '/test');
+ expectToBe(location.path(), '/test1');
});
});
}));
- it("... should navigate to 'test' from /test", waitForAsync(() => {
+ it("... should navigate to 'test1' from /test1", waitForAsync(() => {
fixture.ngZone.run(() => {
- router.navigate(['/test']).then(() => {
- expectToBe(location.path(), '/test');
+ router.navigate(['/test1']).then(() => {
+ expectToBe(location.path(), '/test1');
});
});
}));
@@ -142,6 +172,14 @@ describe('AppComponent (DONE)', () => {
});
});
}));
+
+ it("... should navigate to '/test2/test3' from /test2/test3", waitForAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigate(['/test2/test3']).then(() => {
+ expectToBe(location.path(), '/test2/test3');
+ });
+ });
+ }));
});
describe('BEFORE initial data binding', () => {
@@ -157,7 +195,7 @@ describe('AppComponent (DONE)', () => {
it('... should call AnalyticsService to track page view after navigation', waitForAsync(() => {
fixture.ngZone.run(() => {
router.navigate(['']).then(() => {
- expectSpyCall(trackpageViewSpy, 1, '/test');
+ expectSpyCall(trackpageViewSpy, 1, '/test1');
});
});
}));
@@ -165,13 +203,13 @@ describe('AppComponent (DONE)', () => {
it('... should call AnalyticsService to track page view after navigation changed', waitForAsync(() => {
fixture.ngZone.run(() => {
router.navigate(['']).then(() => {
- expectSpyCall(trackpageViewSpy, 1, '/test');
+ expectSpyCall(trackpageViewSpy, 1, '/test1');
- router.navigate(['test2']).then(() => {
+ router.navigate(['/test2']).then(() => {
expectSpyCall(trackpageViewSpy, 2, '/test2');
- router.navigate(['test']).then(() => {
- expectSpyCall(trackpageViewSpy, 3, '/test');
+ router.navigate(['/test1']).then(() => {
+ expectSpyCall(trackpageViewSpy, 3, '/test1');
});
});
});
@@ -179,6 +217,12 @@ describe('AppComponent (DONE)', () => {
}));
});
+ describe('EditionInit', () => {
+ it('... should call EditionInitService to initialize edition', () => {
+ expectSpyCall(initializeEditionSpy, 1);
+ });
+ });
+
describe('VIEW', () => {
it('... should contain one header component (stubbed)', () => {
getAndExpectDebugElementByDirective(compDe, NavbarStubComponent, 1, 1);
@@ -192,5 +236,35 @@ describe('AppComponent (DONE)', () => {
getAndExpectDebugElementByDirective(compDe, FooterStubComponent, 1, 1);
});
});
+
+ describe('Title', () => {
+ it('... should have called getTitle', () => {
+ expectSpyCall(getTitleSpy, 1);
+ });
+
+ it('... should not have called setTitle', () => {
+ expectSpyCall(setTitleSpy, 0);
+ });
+
+ it('... should set the custom page title from route data if available', waitForAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigate(['/test1']).then(() => {
+ expectSpyCall(setTitleSpy, 1, 'Custom Page Title 1');
+
+ router.navigate(['/test2/test3']).then(() => {
+ expectSpyCall(setTitleSpy, 2, 'Custom Page Title 3');
+ });
+ });
+ });
+ }));
+
+ it('... should set the default page title if route data title is not available', waitForAsync(() => {
+ fixture.ngZone.run(() => {
+ router.navigate(['/test2']).then(() => {
+ expectSpyCall(setTitleSpy, 1, 'Default Page Title');
+ });
+ });
+ }));
+ });
});
});
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index b84ab2daf..9d56d5b9c 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -6,7 +6,7 @@ import { filter, map } from 'rxjs/operators';
import { NgbConfig } from '@ng-bootstrap/ng-bootstrap';
-import { AnalyticsService } from '@awg-core/services';
+import { AnalyticsService, EditionInitService } from '@awg-core/services';
/**
* The main component of the AWG App.
@@ -33,6 +33,7 @@ export class AppComponent {
constructor(
private readonly activatedRoute: ActivatedRoute,
private analyticsService: AnalyticsService,
+ private editionInitService: EditionInitService,
ngbConfig: NgbConfig,
private readonly router: Router,
private titleService: Title
@@ -47,6 +48,9 @@ export class AppComponent {
// Init analytics
this.analyticsService.initializeAnalytics();
+ // Init edition complexes and outline
+ this.editionInitService.initializeEdition();
+
// Track router events
this.router.events
.pipe(
diff --git a/src/app/app.globals.ts b/src/app/app.globals.ts
index 0c64d79be..ec89388bb 100644
--- a/src/app/app.globals.ts
+++ b/src/app/app.globals.ts
@@ -1,15 +1,15 @@
// THIS IS AN AUTO-GENERATED FILE. DO NOT CHANGE IT MANUALLY!
-// Generated last time on Mon, Jul 1, 2024 3:28:42 PM
+// Generated last time on Mon, Aug 19, 2024 7:32:05 PM
/**
* The latest version of the AWG App
*/
-export const appVersion = '0.12.3';
+export const appVersion = '0.14.0';
/**
* The release date of the latest version of the AWG App
*/
-export const appVersionReleaseDate = '01. Juli 2024';
+export const appVersionReleaseDate = '19. August 2024';
/**
* The URL of the AWG App
diff --git a/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts b/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts
index 8d1e0345b..8573ca84e 100644
--- a/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts
+++ b/src/app/core/footer/footer-declaration/footer-declaration.component.spec.ts
@@ -70,11 +70,8 @@ describe('FooterDeclarationComponent (DONE)', () => {
const versionDateEl = versionDateDes[0].nativeElement;
// Check output
- expect(versionEl.textContent).toBeDefined();
- expect(versionEl.textContent).toBeFalsy();
-
- expect(versionDateEl.textContent).toBeDefined();
- expect(versionDateEl.textContent).toBeFalsy();
+ expectToBe(versionEl.textContent, '');
+ expectToBe(versionDateEl.textContent, '');
});
});
});
@@ -133,7 +130,7 @@ describe('FooterDeclarationComponent (DONE)', () => {
const imprintLinkDe = linkDes[0]; // Contact link DebugElement
const imprintLink = routerLinks[0]; // Contact link directive
- expect(imprintLink.navigatedTo).toBeNull();
+ expectToBe(imprintLink.navigatedTo, null);
click(imprintLinkDe);
fixture.detectChanges();
@@ -146,7 +143,7 @@ describe('FooterDeclarationComponent (DONE)', () => {
const documentationLinkDe = linkDes[1]; // Contact link DebugElement
const documentationLink = routerLinks[1]; // Contact link directive
- expect(documentationLink.navigatedTo).toBeNull();
+ expectToBe(documentationLink.navigatedTo, null);
click(documentationLinkDe);
fixture.detectChanges();
diff --git a/src/app/core/footer/footer.component.spec.ts b/src/app/core/footer/footer.component.spec.ts
index 5872ceb3f..31e1cde84 100644
--- a/src/app/core/footer/footer.component.spec.ts
+++ b/src/app/core/footer/footer.component.spec.ts
@@ -97,7 +97,7 @@ describe('FooterComponent (DONE)', () => {
it('... injected service should use provided mockValue', () => {
const coreService = TestBed.inject(CoreService);
- expect(mockCoreService === coreService).toBeTrue();
+ expectToBe(mockCoreService === coreService, true);
});
describe('BEFORE initial data binding', () => {
diff --git a/src/app/core/interceptors/caching/caching.interceptor.spec.ts b/src/app/core/interceptors/caching/caching.interceptor.spec.ts
index 75c05297f..b02da4a47 100644
--- a/src/app/core/interceptors/caching/caching.interceptor.spec.ts
+++ b/src/app/core/interceptors/caching/caching.interceptor.spec.ts
@@ -134,12 +134,12 @@ describe('CachingInterceptor (DONE)', () => {
// Spied service call returns created response
expectToEqual(httpCacheService.get(expectedRequest), expectedResponse);
// Real service does not have created response
- expect((httpCacheService as any)._cachedResponses.has(expectedRequest.urlWithParams)).toBeFalse();
+ expectToBe((httpCacheService as any)._cachedResponses.has(expectedRequest.urlWithParams), false);
}));
it('... should clear mock cache after each run', waitForAsync(() => {
- expect(mockCache.get(expectedRequest)).toBeNull();
- expect(httpCacheService.get(expectedRequest)).toBeNull();
+ expectToBe(mockCache.get(expectedRequest), null);
+ expectToBe(httpCacheService.get(expectedRequest), null);
}));
it('... should use mock console', () => {
@@ -231,7 +231,7 @@ describe('CachingInterceptor (DONE)', () => {
const expectedRequest = new HttpRequest('GET', expectedUrl);
// Mock cache is empty
- expect(mockCache.get(expectedRequest)).toBeNull();
+ expectToBe(mockCache.get(expectedRequest), null);
// Subscribe to GET Http Request
const sub = httpClient.get(expectedUrl).subscribe({
@@ -293,7 +293,7 @@ describe('CachingInterceptor (DONE)', () => {
const expectedRequest = new HttpRequest('GET', expectedUrl);
// No cached response in cache
- expect(mockCache.get(expectedRequest)).toBeNull();
+ expectToBe(mockCache.get(expectedRequest), null);
// Subscribe to GET Http Request
httpClient.get(expectedUrl).subscribe({
diff --git a/src/app/core/navbar/navbar.component.html b/src/app/core/navbar/navbar.component.html
index 81bf10b99..3f040cb8c 100644
--- a/src/app/core/navbar/navbar.component.html
+++ b/src/app/core/navbar/navbar.component.html
@@ -50,14 +50,21 @@
routerLinkActive="active"
>{{ editionRouteConstants.ROWTABLES.full }}
+ {{ editionRouteConstants.PREFACE.full }}
@for (editionComplex of DISPLAYED_EDITION_COMPLEXES; track editionComplex.complexId.short) {
diff --git a/src/app/core/navbar/navbar.component.spec.ts b/src/app/core/navbar/navbar.component.spec.ts
index c8c7373b6..41da104b5 100644
--- a/src/app/core/navbar/navbar.component.spec.ts
+++ b/src/app/core/navbar/navbar.component.spec.ts
@@ -3,18 +3,6 @@ import { DebugElement, NgModule } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
import { Router } from '@angular/router';
-import { cleanStylesFromDOM } from '@testing/clean-up-helper';
-import { click, clickAndAwaitChanges } from '@testing/click-helper';
-import {
- expectSpyCall,
- expectToBe,
- expectToContain,
- expectToEqual,
- getAndExpectDebugElementByCss,
- getAndExpectDebugElementByDirective,
-} from '@testing/expect-helper';
-import { RouterLinkStubDirective } from '@testing/router-stubs';
-
import Spy = jasmine.Spy;
import { FontAwesomeTestingModule } from '@fortawesome/angular-fontawesome/testing';
@@ -28,13 +16,25 @@ import {
} from '@fortawesome/free-solid-svg-icons';
import { NgbCollapseModule, NgbConfig, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
+import { click, clickAndAwaitChanges } from '@testing/click-helper';
+import {
+ expectSpyCall,
+ expectToBe,
+ expectToContain,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+ getAndExpectDebugElementByDirective,
+} from '@testing/expect-helper';
+import { RouterLinkStubDirective } from '@testing/router-stubs';
+
import { LOGOSDATA } from '@awg-core/core-data';
import { Logos } from '@awg-core/core-models';
import { CoreService } from '@awg-core/services';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import { EditionComplex } from '@awg-views/edition-view/models';
+import { EditionComplexesService } from '@awg-views/edition-view/services';
import { NavbarComponent } from './navbar.component';
@@ -44,6 +44,7 @@ function generateExpectedOrderOfRouterlinks(editionComplexes: EditionComplex[]):
['/home'],
[EDITION_ROUTE_CONSTANTS.EDITION.route, EDITION_ROUTE_CONSTANTS.SERIES.route],
[EDITION_ROUTE_CONSTANTS.EDITION.route, EDITION_ROUTE_CONSTANTS.ROWTABLES.route],
+ [EDITION_ROUTE_CONSTANTS.EDITION.route, EDITION_ROUTE_CONSTANTS.PREFACE.route],
];
const editionLinks = editionComplexes.flatMap(complex => [
@@ -66,7 +67,6 @@ describe('NavbarComponent (DONE)', () => {
let routerLinks;
let coreServiceSpy: Spy;
- let getEditionComplexSpy: Spy;
let isActiveRouteSpy: Spy;
let routerSpy: Spy;
let provideMetaDataSpy: Spy;
@@ -84,7 +84,6 @@ describe('NavbarComponent (DONE)', () => {
let expectedStructureIcon: IconDefinition;
let expectedEditionComplexes: EditionComplex[];
- let expectedSelectedEditionComplex: EditionComplex = EDITION_COMPLEXES.OP12;
let expectedOrderOfRouterlinks: string[][];
const expectedEditionRouteConstants: typeof EDITION_ROUTE_CONSTANTS = EDITION_ROUTE_CONSTANTS;
@@ -117,6 +116,10 @@ describe('NavbarComponent (DONE)', () => {
}).compileComponents();
}));
+ beforeAll(() => {
+ EditionComplexesService.initializeEditionComplexesList();
+ });
+
beforeEach(() => {
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
@@ -126,19 +129,18 @@ describe('NavbarComponent (DONE)', () => {
expectedLogos = LOGOSDATA;
expectedEditionComplexes = [
- EDITION_COMPLEXES.OP3,
- EDITION_COMPLEXES.OP4,
- EDITION_COMPLEXES.OP12,
- EDITION_COMPLEXES.OP23,
- EDITION_COMPLEXES.OP25,
- EDITION_COMPLEXES.M22,
- EDITION_COMPLEXES.M30,
- EDITION_COMPLEXES.M31,
- EDITION_COMPLEXES.M34,
- EDITION_COMPLEXES.M35_42,
- EDITION_COMPLEXES.M37,
+ EditionComplexesService.getEditionComplexById('OP3'),
+ EditionComplexesService.getEditionComplexById('OP4'),
+ EditionComplexesService.getEditionComplexById('OP12'),
+ EditionComplexesService.getEditionComplexById('OP23'),
+ EditionComplexesService.getEditionComplexById('OP25'),
+ EditionComplexesService.getEditionComplexById('M22'),
+ EditionComplexesService.getEditionComplexById('M30'),
+ EditionComplexesService.getEditionComplexById('M31'),
+ EditionComplexesService.getEditionComplexById('M34'),
+ EditionComplexesService.getEditionComplexById('M35_42'),
+ EditionComplexesService.getEditionComplexById('M37'),
];
- expectedSelectedEditionComplex = expectedEditionComplexes[0];
expectedOrderOfRouterlinks = generateExpectedOrderOfRouterlinks(expectedEditionComplexes);
expectedContactIcon = faEnvelope;
@@ -151,7 +153,6 @@ describe('NavbarComponent (DONE)', () => {
// `.and.callThrough` will track the spy down the nested describes, see
// https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3Eand.callThrough%3C/code%3E
coreServiceSpy = spyOn(mockCoreService, 'getLogos').and.callThrough();
- getEditionComplexSpy = spyOn(component, 'getEditionComplex').and.callThrough();
isActiveRouteSpy = spyOn(component, 'isActiveRoute').and.callThrough();
routerSpy = mockRouter.isActive as jasmine.Spy;
provideMetaDataSpy = spyOn(component, 'provideMetaData').and.callThrough();
@@ -168,7 +169,7 @@ describe('NavbarComponent (DONE)', () => {
it('... injected service should use provided mockValue', () => {
const coreService = TestBed.inject(CoreService);
- expect(mockCoreService === coreService).toBe(true);
+ expectToBe(mockCoreService === coreService, true);
});
describe('BEFORE initial data binding', () => {
@@ -185,7 +186,7 @@ describe('NavbarComponent (DONE)', () => {
});
it('... should have `isCollapsed = true`', () => {
- expect(component.isCollapsed).toBeTrue();
+ expectToBe(component.isCollapsed, true);
});
it('... should have `DISPLAYED_EDITION_COMPLEXES`', () => {
@@ -204,10 +205,6 @@ describe('NavbarComponent (DONE)', () => {
expect(component.logos).toBeUndefined();
});
- it('... should not have `selectedEditionComplex`', () => {
- expect(component.selectedEditionComplex).toBeUndefined();
- });
-
describe('VIEW', () => {
it('... should contain 1 navbar', () => {
getAndExpectDebugElementByCss(compDe, 'nav.navbar', 1, 1);
@@ -319,20 +316,6 @@ describe('NavbarComponent (DONE)', () => {
});
});
- describe('#getEditionComplex()', () => {
- it('... should have a method `getEditionComplex`', () => {
- expect(component.getEditionComplex).toBeDefined();
- });
-
- it('... should not have been called', () => {
- expectSpyCall(getEditionComplexSpy, 0);
- });
-
- it('... should not have `selectedEditionComplex`', () => {
- expect(component.selectedEditionComplex).toBeUndefined();
- });
- });
-
describe('#isActiveRoute()', () => {
it('... should have a method `isActiveRoute`', () => {
expect(component.isActiveRoute).toBeDefined();
@@ -384,15 +367,15 @@ describe('NavbarComponent (DONE)', () => {
it('... should toggle `isCollapsed`', () => {
component.toggleNav();
- expect(component.isCollapsed).toBeFalse();
+ expectToBe(component.isCollapsed, false);
component.toggleNav();
- expect(component.isCollapsed).toBeTrue();
+ expectToBe(component.isCollapsed, true);
component.toggleNav();
- expect(component.isCollapsed).toBeFalse();
+ expectToBe(component.isCollapsed, false);
});
});
});
@@ -453,7 +436,7 @@ describe('NavbarComponent (DONE)', () => {
expectToEqual(faIconIns, expectedContactIcon);
});
- describe('... second nav-item link', () => {
+ describe('... second nav-item link (edition)', () => {
let navItemDe: DebugElement[];
let navItemLinkDe: DebugElement[];
@@ -466,7 +449,6 @@ describe('NavbarComponent (DONE)', () => {
}));
it('... should have a dropdown menu', () => {
- // Expect dropdown menu
getAndExpectDebugElementByCss(navItemDe[1], 'div.dropdown-menu', 1, 1);
});
@@ -482,48 +464,56 @@ describe('NavbarComponent (DONE)', () => {
expectToBe(headerEl.textContent, 'Allgemein');
});
- it('... should be followed by 2 dropdown items', () => {
- const firstItemDe = getAndExpectDebugElementByCss(
+ it('... should be followed by 3 dropdown items for edition overview, rowtables and preface', () => {
+ const overviewDe = getAndExpectDebugElementByCss(
navItemDe[1],
'div.dropdown-menu > a.dropdown-item:nth-child(2)',
1,
1
);
- const secondItemDe = getAndExpectDebugElementByCss(
+ const rowtablesDe = getAndExpectDebugElementByCss(
navItemDe[1],
'div.dropdown-menu > a.dropdown-item:nth-child(3)',
1,
1
);
+ const prefaceDe = getAndExpectDebugElementByCss(
+ navItemDe[1],
+ 'div.dropdown-menu > a.dropdown-item:nth-child(4)',
+ 1,
+ 1
+ );
- const firstItemEl = firstItemDe[0].nativeElement;
- const secondItemEl = secondItemDe[0].nativeElement;
+ const overviewEl = overviewDe[0].nativeElement;
+ const rowtablesEl = rowtablesDe[0].nativeElement;
+ const prefaceEl = prefaceDe[0].nativeElement;
- expectToBe(firstItemEl.textContent, EDITION_ROUTE_CONSTANTS.SERIES.full);
- expectToBe(secondItemEl.textContent, EDITION_ROUTE_CONSTANTS.ROWTABLES.full);
+ expectToBe(overviewEl.textContent, EDITION_ROUTE_CONSTANTS.SERIES.full);
+ expectToBe(rowtablesEl.textContent, EDITION_ROUTE_CONSTANTS.ROWTABLES.full);
+ expectToBe(prefaceEl.textContent, EDITION_ROUTE_CONSTANTS.PREFACE.full);
});
it('... should have another dropdown header `Auswahl Skizzenkomplexe` surrounded by dividers', () => {
getAndExpectDebugElementByCss(
navItemDe[1],
- 'div.dropdown-menu > div.dropdown-divider:nth-child(4)',
+ 'div.dropdown-menu > div.dropdown-divider:nth-child(5)',
1,
1
);
- getAndExpectDebugElementByCss(
+ const headerDe = getAndExpectDebugElementByCss(
navItemDe[1],
- 'div.dropdown-menu > div.dropdown-divider:nth-child(6)',
+ 'div.dropdown-menu > h6.dropdown-header:nth-child(6)',
1,
1
);
+ const headerEl = headerDe[0].nativeElement;
- const headerDe = getAndExpectDebugElementByCss(
+ getAndExpectDebugElementByCss(
navItemDe[1],
- 'div.dropdown-menu > h6.dropdown-header:nth-child(5)',
+ 'div.dropdown-menu > div.dropdown-divider:nth-child(7)',
1,
1
);
- const headerEl = headerDe[0].nativeElement;
expectToBe(headerEl.textContent, 'Auswahl Skizzenkomplexe');
});
@@ -567,7 +557,11 @@ describe('NavbarComponent (DONE)', () => {
const headerSpanDe = getAndExpectDebugElementByCss(headerDe[0], 'span', 1, 1);
const headerSpanEl = headerSpanDe[0].nativeElement;
- const headerSiglum = `[AWG ${expectedEditionComplexes[index].series.short}/${expectedEditionComplexes[index].section.short}] `;
+ const awg = EDITION_ROUTE_CONSTANTS.EDITION.short;
+ const series = expectedEditionComplexes[index].pubStatement.series.short;
+ const section = expectedEditionComplexes[index].pubStatement.section.short;
+
+ const headerSiglum = `[${awg} ${series}/${section}] `;
const headerId = expectedEditionComplexes[index].complexId.full;
expectToContain(headerEl.textContent, headerSiglum);
@@ -598,17 +592,6 @@ describe('NavbarComponent (DONE)', () => {
});
});
- describe('#getEditionComplex()', () => {
- it('... should have been called', () => {
- expectSpyCall(getEditionComplexSpy, 1);
- });
-
- it('... should get `selectedEditionComplex`', () => {
- expect(component.selectedEditionComplex).toBeDefined();
- expectToEqual(component.selectedEditionComplex, expectedSelectedEditionComplex);
- });
- });
-
describe('#isActiveRoute()', () => {
it('... should have been called 2 times', () => {
expectSpyCall(isActiveRouteSpy, 2);
@@ -618,14 +601,14 @@ describe('NavbarComponent (DONE)', () => {
const expectedActiveRoute = '/active-route';
routerSpy.and.returnValue(true);
- expect(component.isActiveRoute(expectedActiveRoute)).toBeTrue();
+ expectToBe(component.isActiveRoute(expectedActiveRoute), true);
});
it('... should return false if a given route is not active', () => {
const expectedActiveRoute = '/non-active-route';
routerSpy.and.returnValue(false);
- expect(component.isActiveRoute(expectedActiveRoute)).toBeFalse();
+ expectToBe(component.isActiveRoute(expectedActiveRoute), false);
});
});
@@ -672,7 +655,7 @@ describe('NavbarComponent (DONE)', () => {
const linkDe = linkDes[index];
const expectedRouterLink = expectedOrderOfRouterlinks[index];
- expect(routerLink.navigatedTo).toBeNull();
+ expectToBe(routerLink.navigatedTo, null);
click(linkDe);
fixture.detectChanges();
diff --git a/src/app/core/navbar/navbar.component.ts b/src/app/core/navbar/navbar.component.ts
index 4e0a0223b..81f6351c7 100644
--- a/src/app/core/navbar/navbar.component.ts
+++ b/src/app/core/navbar/navbar.component.ts
@@ -5,9 +5,9 @@ import { faEnvelope, faFileAlt, faHome, faNetworkWired, faSearch } from '@fortaw
import { Logos } from '@awg-core/core-models';
import { CoreService } from '@awg-core/services';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import { EditionComplex } from '@awg-views/edition-view/models';
+import { EditionComplexesService } from '@awg-views/edition-view/services';
/**
* The Header component.
@@ -70,30 +70,23 @@ export class NavbarComponent implements OnInit {
*/
logos: Logos;
- /**
- * Public variable: selectedEditionComplex.
- *
- * It keeps the currently selected edition complex.
- */
- selectedEditionComplex: EditionComplex;
-
/**
* Readonly variable: DISPLAYED_EDITION_COMPLEXES.
*
* It keeps the array of displayed edition complexes.
*/
readonly DISPLAYED_EDITION_COMPLEXES: EditionComplex[] = [
- EDITION_COMPLEXES.OP3,
- EDITION_COMPLEXES.OP4,
- EDITION_COMPLEXES.OP12,
- EDITION_COMPLEXES.OP23,
- EDITION_COMPLEXES.OP25,
- EDITION_COMPLEXES.M22,
- EDITION_COMPLEXES.M30,
- EDITION_COMPLEXES.M31,
- EDITION_COMPLEXES.M34,
- EDITION_COMPLEXES.M35_42,
- EDITION_COMPLEXES.M37,
+ EditionComplexesService.getEditionComplexById('OP3'),
+ EditionComplexesService.getEditionComplexById('OP4'),
+ EditionComplexesService.getEditionComplexById('OP12'),
+ EditionComplexesService.getEditionComplexById('OP23'),
+ EditionComplexesService.getEditionComplexById('OP25'),
+ EditionComplexesService.getEditionComplexById('M22'),
+ EditionComplexesService.getEditionComplexById('M30'),
+ EditionComplexesService.getEditionComplexById('M31'),
+ EditionComplexesService.getEditionComplexById('M34'),
+ EditionComplexesService.getEditionComplexById('M35_42'),
+ EditionComplexesService.getEditionComplexById('M37'),
];
/**
@@ -125,7 +118,6 @@ export class NavbarComponent implements OnInit {
* when initializing the component.
*/
ngOnInit() {
- this.getEditionComplex();
this.provideMetaData();
}
@@ -147,17 +139,6 @@ export class NavbarComponent implements OnInit {
});
}
- /**
- * Public method: getEditionComplex.
- *
- * It gets the selected edition complex.
- *
- * @returns {void} Sets the selectedEditionComplex variable.
- */
- getEditionComplex(): void {
- this.selectedEditionComplex = this.DISPLAYED_EDITION_COMPLEXES[0];
- }
-
/**
* Public method: provideMetaData.
*
diff --git a/src/app/core/services/analytics-sercvice/analytics.service.spec.ts b/src/app/core/services/analytics-sercvice/analytics.service.spec.ts
index ead665c9d..c25cf6c15 100644
--- a/src/app/core/services/analytics-sercvice/analytics.service.spec.ts
+++ b/src/app/core/services/analytics-sercvice/analytics.service.spec.ts
@@ -93,7 +93,7 @@ describe('AnalyticsService (DONE)', () => {
});
it('... should clear mock analytics store after each run', () => {
- expect(mockAnalytics.getGtag(0)).toBeNull();
+ expectToBe(mockAnalytics.getGtag(0), null);
});
});
@@ -107,7 +107,7 @@ describe('AnalyticsService (DONE)', () => {
setupAnalytics(analyticsService, null, expectedAnalyticsId);
expectSpyCall(initializeAnalyticsSpy, 1);
- expect((analyticsService as any)._isInitialized).toBeFalse();
+ expectToBe((analyticsService as any)._isInitialized, false);
});
it('... should not initialize the analytics tracker without analyticsId', () => {
@@ -115,14 +115,14 @@ describe('AnalyticsService (DONE)', () => {
setupAnalytics(analyticsService, expectedAnalyticsEndpoint, null);
expectSpyCall(initializeAnalyticsSpy, 1);
- expect((analyticsService as any)._isInitialized).toBeFalse();
+ expectToBe((analyticsService as any)._isInitialized, false);
});
it('... should initialize the analytics tracker with given endpoint and id', () => {
setupAnalytics(analyticsService, expectedAnalyticsEndpoint, expectedAnalyticsId);
expectSpyCall(initializeAnalyticsSpy, 1);
- expect((analyticsService as any)._isInitialized).toBeTrue();
+ expectToBe((analyticsService as any)._isInitialized, true);
});
it('... should log a replacement message in develop mode', () => {
@@ -180,7 +180,7 @@ describe('AnalyticsService (DONE)', () => {
analyticsService.trackPageView(expectedPage);
expectSpyCall(gtagSpy, 0, null);
- expect(gtagSpy.calls.any()).toBeFalse();
+ expectToBe(gtagSpy.calls.any(), false);
});
it('... should do nothing if isInitialized is set to false', () => {
@@ -189,7 +189,7 @@ describe('AnalyticsService (DONE)', () => {
analyticsService.trackPageView(expectedPage);
expectSpyCall(gtagSpy, 0, null);
- expect(gtagSpy.calls.any()).toBeFalse();
+ expectToBe(gtagSpy.calls.any(), false);
});
it('... should run if analytics is initialized successfully', () => {
@@ -216,7 +216,7 @@ describe('AnalyticsService (DONE)', () => {
analyticsService.trackPageView(null);
expectSpyCall(gtagSpy, 0, null);
- expect(gtagSpy.calls.any()).toBeFalse();
+ expectToBe(gtagSpy.calls.any(), false);
});
it('... should track the given page', () => {
diff --git a/src/app/core/services/api-service/api.service.spec.ts b/src/app/core/services/api-service/api.service.spec.ts
index 7a6ccb289..31958d6dd 100644
--- a/src/app/core/services/api-service/api.service.spec.ts
+++ b/src/app/core/services/api-service/api.service.spec.ts
@@ -92,8 +92,7 @@ describe('ApiService', () => {
});
it("... should have empty 'httpGetUrl'", () => {
- expect(apiService.httpGetUrl).toBeDefined();
- expect(apiService.httpGetUrl).toBeFalsy();
+ expectToBe(apiService.httpGetUrl, '');
});
});
@@ -159,6 +158,7 @@ describe('ApiService', () => {
expectToBe(call.request.method, 'GET');
expectToBe(call.request.responseType, 'json');
expectToEqual(call.request.url, expectedUrl);
+
expect(call.request.params).toBeDefined();
expectToBe(call.request.params.keys().length, 0);
}));
@@ -182,6 +182,7 @@ describe('ApiService', () => {
expectToBe(call.request.method, 'GET');
expectToBe(call.request.responseType, 'json');
expectToEqual(call.request.url, expectedUrl);
+
expect(call.request.params).toBeDefined();
expectToBe(call.request.params.keys().length, 2);
expectToBe(call.request.params.get('searchtype'), expectedSearchType);
diff --git a/src/app/core/services/conversion-service/conversion.service.spec.ts b/src/app/core/services/conversion-service/conversion.service.spec.ts
index 46583d147..08c7a16ae 100644
--- a/src/app/core/services/conversion-service/conversion.service.spec.ts
+++ b/src/app/core/services/conversion-service/conversion.service.spec.ts
@@ -73,7 +73,7 @@ describe('ConversionService', () => {
const result = conversionService.convertFullTextSearchResults(searchResponse);
- expect(result).toEqual(searchResponse);
+ expectToEqual(result, searchResponse);
});
it('... subjects are null', () => {
@@ -82,7 +82,7 @@ describe('ConversionService', () => {
const result = conversionService.convertFullTextSearchResults(searchResponse);
- expect(result).toEqual(searchResponse);
+ expectToEqual(result, searchResponse);
});
it('... subjects are empty', () => {
@@ -91,7 +91,7 @@ describe('ConversionService', () => {
const result = conversionService.convertFullTextSearchResults(searchResponse);
- expect(result).toEqual(searchResponse);
+ expectToEqual(result, searchResponse);
});
});
@@ -245,7 +245,7 @@ describe('ConversionService', () => {
const result = conversionService.prepareFullTextSearchResultText(searchResponseWithQuery, searchUrl);
- expect(typeof result).toEqual('string');
+ expectToBe(typeof result, 'string');
});
describe('... should return correct text', () => {
@@ -339,7 +339,7 @@ describe('ConversionService', () => {
const result = (conversionService as any)._cleanSubjectValueLabels(subject);
- expect(result.valuelabel).toBeNull();
+ expectToBe(result.valuelabel, null);
expectToBe(result.obj_id, '');
});
@@ -463,7 +463,7 @@ describe('ConversionService', () => {
const result = (conversionService as any)._convertDateValue(dateObj);
- expect(typeof result).toEqual('string');
+ expectToBe(typeof result, 'string');
});
it('should return the converted date string without " (G)"', () => {
@@ -543,7 +543,7 @@ describe('ConversionService', () => {
const result = (conversionService as any)._convertLinkValue(valueId, firstProp, restype);
- expect(typeof result).toEqual('string');
+ expectToBe(typeof result, 'string');
});
it('... should return a linked value', () => {
@@ -642,7 +642,7 @@ describe('ConversionService', () => {
const result = (conversionService as any)._convertRichtextValue(str, JSON.stringify(jsonAttrs));
- expect(typeof result).toEqual('string');
+ expectToBe(typeof result, 'string');
});
it('... should correctly convert a rich text value with Standoff to HTML', () => {
@@ -728,7 +728,7 @@ describe('ConversionService', () => {
const result = (conversionService as any)._convertStandoffToHTML(str, JSON.stringify(jsonAttrs));
- expect(typeof result).toEqual('string');
+ expectToBe(typeof result, 'string');
});
it('... should correctly convert a rich text value with Standoff to HTML', () => {
diff --git a/src/app/core/services/edition-init-service/edition-init.service.spec.ts b/src/app/core/services/edition-init-service/edition-init.service.spec.ts
new file mode 100644
index 000000000..ab24a010c
--- /dev/null
+++ b/src/app/core/services/edition-init-service/edition-init.service.spec.ts
@@ -0,0 +1,88 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+import { TestBed } from '@angular/core/testing';
+
+import Spy = jasmine.Spy;
+
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
+import { expectSpyCall, expectToEqual } from '@testing/expect-helper';
+
+import { EDITION_ROUTE_CONSTANTS } from '@awg-app/views/edition-view/edition-route-constants';
+import { EditionComplexesService, EditionOutlineService } from '@awg-app/views/edition-view/services';
+
+import { EditionInitService } from './edition-init.service';
+
+describe('EditionInitService (DONE)', () => {
+ let editionInitService: EditionInitService;
+
+ let initializeEditionComplexesListSpy: Spy;
+ let initializeEditionOutlineSpy: Spy;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [EditionInitService],
+ });
+
+ // Inject service
+ editionInitService = TestBed.inject(EditionInitService);
+
+ // Spies for service methods
+ initializeEditionComplexesListSpy = spyOn(
+ EditionComplexesService,
+ 'initializeEditionComplexesList'
+ ).and.callThrough();
+ initializeEditionOutlineSpy = spyOn(EditionOutlineService, 'initializeEditionOutline').and.callThrough();
+ });
+
+ afterAll(() => {
+ cleanStylesFromDOM();
+ });
+
+ it('... should create', () => {
+ expect(editionInitService).toBeTruthy();
+ });
+
+ describe('#initializeEdition()', () => {
+ it('... should have a method `initializeEdition`', () => {
+ expect(editionInitService.initializeEdition).toBeDefined();
+ });
+
+ it('... should initialize the edition view', () => {
+ editionInitService.initializeEdition();
+
+ expectSpyCall(initializeEditionComplexesListSpy, 1);
+ expectSpyCall(initializeEditionOutlineSpy, 1);
+ });
+
+ it('... should make the EditionComplexesList available', () => {
+ editionInitService.initializeEdition();
+
+ const editionComplexesList = EditionComplexesService.getEditionComplexesList();
+
+ expect(editionComplexesList).toBeDefined();
+ expect(editionComplexesList).not.toBe({});
+
+ // Test for samples
+ expect(editionComplexesList['OP3']).toBeDefined();
+ expect(editionComplexesList['M22']).toBeDefined();
+
+ // Test for sample properties
+ expect(editionComplexesList['OP3'].titleStatement).toBeDefined();
+ expect(editionComplexesList['OP3'].respStatement).toBeDefined();
+ expect(editionComplexesList['OP3'].pubStatement).toBeDefined();
+ });
+
+ it('... should make the EditionOutline available', () => {
+ editionInitService.initializeEdition();
+
+ const editionOutline = EditionOutlineService.getEditionOutline();
+
+ expect(editionOutline).toBeDefined();
+ expect(editionOutline).not.toBe([]);
+
+ // Test for samples
+ expectToEqual(editionOutline[0].series, EDITION_ROUTE_CONSTANTS.SERIES_1);
+ expectToEqual(editionOutline[1].series, EDITION_ROUTE_CONSTANTS.SERIES_2);
+ expectToEqual(editionOutline[2].series, EDITION_ROUTE_CONSTANTS.SERIES_3);
+ });
+ });
+});
diff --git a/src/app/core/services/edition-init-service/edition-init.service.ts b/src/app/core/services/edition-init-service/edition-init.service.ts
new file mode 100644
index 000000000..2fefd7aad
--- /dev/null
+++ b/src/app/core/services/edition-init-service/edition-init.service.ts
@@ -0,0 +1,28 @@
+import { Injectable } from '@angular/core';
+
+import { EditionComplexesService, EditionOutlineService } from '@awg-views/edition-view/services';
+
+/**
+ * The EditionInit service.
+ *
+ * It handles the initialization of the edition view.
+ *
+ * Provided in: `root`.
+ */
+@Injectable({
+ providedIn: 'root',
+})
+export class EditionInitService {
+ /**
+ * Public method: initializeEdition.
+ *
+ * It initializes the edition view by initializing
+ * the edition complexes list and the edition outline.
+ *
+ * @returns {void} Initializes the edition view.
+ */
+ initializeEdition(): void {
+ EditionComplexesService.initializeEditionComplexesList();
+ EditionOutlineService.initializeEditionOutline();
+ }
+}
diff --git a/src/app/core/services/edition-init-service/index.ts b/src/app/core/services/edition-init-service/index.ts
new file mode 100644
index 000000000..178f31691
--- /dev/null
+++ b/src/app/core/services/edition-init-service/index.ts
@@ -0,0 +1 @@
+export * from './edition-init.service';
diff --git a/src/app/core/services/gnd-service/gnd.service.spec.ts b/src/app/core/services/gnd-service/gnd.service.spec.ts
index 013c0af28..925a04b15 100644
--- a/src/app/core/services/gnd-service/gnd.service.spec.ts
+++ b/src/app/core/services/gnd-service/gnd.service.spec.ts
@@ -119,7 +119,7 @@ describe('GndService (DONE)', () => {
expectedStorage.removeItem('testkey');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
});
it('... should use correct mock storage', () => {
@@ -129,7 +129,7 @@ describe('GndService (DONE)', () => {
expectedStorage.setItem('testkey', 'testvalue');
expectToBe(mockStorage.getItem('testkey'), 'testvalue');
- expect(otherMockStorage.getItem('testkey')).toBeNull();
+ expectToBe(otherMockStorage.getItem('testkey'), null);
mockStorage.clear();
otherMockStorage.clear();
@@ -137,7 +137,7 @@ describe('GndService (DONE)', () => {
expectedOtherStorage.setItem('testkey', 'testvalue');
expectToBe(otherMockStorage.getItem('testkey'), 'testvalue');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
otherMockStorage.clear();
});
@@ -155,7 +155,7 @@ describe('GndService (DONE)', () => {
expectedStorage.removeItem('testkey');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
});
it('... should remove the correct item', () => {
@@ -167,17 +167,17 @@ describe('GndService (DONE)', () => {
expectedStorage.removeItem('testkey');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
expectToBe(mockStorage.getItem('testkey2'), 'testvalue2');
expectedStorage.removeItem('testkey2');
- expect(mockStorage.getItem('testkey')).toBeNull();
- expect(mockStorage.getItem('testkey2')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
+ expectToBe(mockStorage.getItem('testkey2'), null);
});
it('... should clear mock storage after each run', () => {
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
});
});
@@ -204,59 +204,59 @@ describe('GndService (DONE)', () => {
describe('... should not do anything if', () => {
it('... gndEvent is undefined', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(undefined);
expectSpyCall(setGndToSessionStorageSpy, 0);
expectSpyCall(removeGndFromSessionStorageSpy, 0);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
it('... gndEvent is null', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(null);
expectSpyCall(setGndToSessionStorageSpy, 0);
expectSpyCall(removeGndFromSessionStorageSpy, 0);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
it('... gndEvent has undefined type', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(new GndEvent(undefined, '123'));
expectSpyCall(setGndToSessionStorageSpy, 0);
expectSpyCall(removeGndFromSessionStorageSpy, 0);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
it('... gndEvent has type null', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(new GndEvent(null, '123'));
expectSpyCall(setGndToSessionStorageSpy, 0);
expectSpyCall(removeGndFromSessionStorageSpy, 0);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
it('... gndEvent has GET type', () => {
const expectedDefaultMessage = 'Got an uncatched GND event';
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(new GndEvent(GndEventType.GET, '123'));
expectSpyCall(setGndToSessionStorageSpy, 0);
expectSpyCall(removeGndFromSessionStorageSpy, 0);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
expectSpyCall(consoleSpy, 1, expectedDefaultMessage);
expectToBe(mockConsole.get(0), expectedDefaultMessage);
@@ -272,7 +272,7 @@ describe('GndService (DONE)', () => {
});
it('... should set key/value pair to storage if given gndEvent type is `set`', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(expectedSetEvent);
@@ -338,39 +338,37 @@ describe('GndService (DONE)', () => {
it('... should set an item to the correct storage if given gndEvent value has gnd link', () => {
const otherMockStorage = mockLocalStorage;
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expect(otherMockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(otherMockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(expectedSetEvent);
- expectToEqual(mockStorage.getItem(expectedGndKey), expectedItem);
- expect(otherMockStorage.getItem(expectedGndKey)).not.toEqual(expectedItem);
- expect(otherMockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), expectedItem);
+ expectToBe(otherMockStorage.getItem(expectedGndKey), null);
otherMockStorage.clear();
});
it('... should overwrite an existing gnd key if gndEvent value has gnd link', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(expectedSetEvent);
- expectToEqual(mockStorage.getItem(expectedGndKey), expectedItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), expectedItem);
gndService.exposeGnd(otherSetEvent);
- expect(mockStorage.getItem(expectedGndKey)).not.toEqual(expectedItem);
- expectToEqual(mockStorage.getItem(expectedGndKey), otherItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), otherItem);
});
it('... should return null if value has no gnd link', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(noLinkGndSetEvent);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
it('... should call helper function with input value to check if value has gnd link', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
const valueHasGndSpy = spyOn
(gndService, '_valueHasGnd').and.callThrough();
gndService.exposeGnd(expectedSetEvent);
@@ -385,7 +383,7 @@ describe('GndService (DONE)', () => {
it('... should execute regex check and populate linkRegArr if value has gnd link', () => {
expect(gndService.linkRegArr).toBeUndefined();
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
const valueHasGndSpy = spyOn(gndService, '_valueHasGnd').and.callFake(checkValue => {
gndService.linkRegArr = gndService.DNB_REG.exec(checkValue);
@@ -400,7 +398,7 @@ describe('GndService (DONE)', () => {
it('... should execute regex check and set linkRegArr = null if value has no gnd link', () => {
expect(gndService.linkRegArr).toBeUndefined();
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
const valueHasGndSpy = spyOn(gndService, '_valueHasGnd').and.callThrough();
gndService.exposeGnd(noLinkGndSetEvent);
@@ -408,30 +406,30 @@ describe('GndService (DONE)', () => {
expectSpyCall(valueHasGndSpy, 1, noLinkGndEventValue);
expect(noLinkGndEventValue).not.toMatch(expectedDnbReg);
- expect(gndService.linkRegArr).toBeNull();
+ expectToBe(gndService.linkRegArr, null);
});
it('... should return true (and set item) if value has gnd link', () => {
expect(gndService.linkRegArr).toBeUndefined();
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
const valueHasGndSpy = spyOn(gndService, '_valueHasGnd').and.callThrough();
gndService.exposeGnd(expectedSetEvent);
expectSpyCall(valueHasGndSpy, 1, expectedGndEventValue);
- expectToEqual(mockStorage.getItem(expectedGndKey), expectedItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), expectedItem);
});
it('... should return false (and set no item) if value has no gnd link', () => {
expect(gndService.linkRegArr).toBeUndefined();
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
const valueHasGndSpy = spyOn(gndService, '_valueHasGnd').and.callThrough();
gndService.exposeGnd(noLinkGndSetEvent);
expectSpyCall(valueHasGndSpy, 1, noLinkGndEventValue);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
});
});
@@ -445,14 +443,14 @@ describe('GndService (DONE)', () => {
});
it('... should remove an item by key from the storage if given gndEvent type is `remove`', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
expectedStorage.setItem(expectedGndKey, expectedItem);
- expectToEqual(mockStorage.getItem(expectedGndKey), expectedItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), expectedItem);
gndService.exposeGnd(expectedRemoveEvent);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
it('... should expose null value if given gndEvent type is `remove`', () => {
@@ -497,19 +495,19 @@ describe('GndService (DONE)', () => {
const expectedOtherStorage = expectedLocalStorage;
const otherMockStorage = mockLocalStorage;
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expect(otherMockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(otherMockStorage.getItem(expectedGndKey), null);
expectedStorage.setItem(expectedGndKey, expectedItem);
expectedOtherStorage.setItem(expectedGndKey, otherItem);
- expectToEqual(mockStorage.getItem(expectedGndKey), expectedItem);
- expectToEqual(otherMockStorage.getItem(expectedGndKey), otherItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), expectedItem);
+ expectToBe(otherMockStorage.getItem(expectedGndKey), otherItem);
gndService.exposeGnd(expectedRemoveEvent);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expectToEqual(otherMockStorage.getItem(expectedGndKey), otherItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(otherMockStorage.getItem(expectedGndKey), otherItem);
otherMockStorage.clear();
});
@@ -517,45 +515,45 @@ describe('GndService (DONE)', () => {
it('... should remove the correct item from the storage', () => {
const otherKey = 'otherKey';
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expect(mockStorage.getItem(otherKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(mockStorage.getItem(otherKey), null);
expectedStorage.setItem(expectedGndKey, expectedItem);
expectedStorage.setItem(otherKey, expectedItem);
- expectToEqual(mockStorage.getItem(expectedGndKey), expectedItem);
- expectToEqual(mockStorage.getItem(otherKey), expectedItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), expectedItem);
+ expectToBe(mockStorage.getItem(otherKey), expectedItem);
gndService.exposeGnd(expectedRemoveEvent);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expectToEqual(mockStorage.getItem(otherKey), expectedItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(mockStorage.getItem(otherKey), expectedItem);
});
describe('... should do nothing if:', () => {
it('- storage has not the gnd key', () => {
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
gndService.exposeGnd(expectedRemoveEvent);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
});
it('- storage has other key but not the gnd key', () => {
const otherKey = 'otherKey';
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expect(mockStorage.getItem(otherKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(mockStorage.getItem(otherKey), null);
expectedStorage.setItem(otherKey, expectedItem);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expectToEqual(mockStorage.getItem(otherKey), expectedItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(mockStorage.getItem(otherKey), expectedItem);
gndService.exposeGnd(expectedRemoveEvent);
- expect(mockStorage.getItem(expectedGndKey)).toBeNull();
- expectToEqual(mockStorage.getItem(otherKey), expectedItem);
+ expectToBe(mockStorage.getItem(expectedGndKey), null);
+ expectToBe(mockStorage.getItem(otherKey), expectedItem);
});
});
});
diff --git a/src/app/core/services/http-cache/http-cache.service.spec.ts b/src/app/core/services/http-cache/http-cache.service.spec.ts
index caa9e48dc..9633c1b9b 100644
--- a/src/app/core/services/http-cache/http-cache.service.spec.ts
+++ b/src/app/core/services/http-cache/http-cache.service.spec.ts
@@ -71,7 +71,7 @@ describe('HttpCacheService (DONE)', () => {
expect(expectedCachedResponse).toBeUndefined();
const expectedGetCache = httpCacheService.get(expectedRequest);
- expect(expectedGetCache).toBeNull();
+ expectToBe(expectedGetCache, null);
});
it('... should return an HTTP response from cache if available', () => {
diff --git a/src/app/core/services/index.ts b/src/app/core/services/index.ts
index 1088a46bd..caadf977c 100644
--- a/src/app/core/services/index.ts
+++ b/src/app/core/services/index.ts
@@ -12,6 +12,7 @@ import { ApiService } from './api-service';
import { ConversionService } from './conversion-service';
import { CoreService } from './core-service';
import { DataStreamerService } from './data-streamer-service';
+import { EditionInitService } from './edition-init-service';
import { GndService } from './gnd-service';
import { HttpCacheService } from './http-cache';
import { LoadingService } from './loading-service';
@@ -25,6 +26,7 @@ export {
ConversionService,
CoreService,
DataStreamerService,
+ EditionInitService,
GndService,
HttpCacheService,
LoadingService,
diff --git a/src/app/core/services/loading-service/loading.service.spec.ts b/src/app/core/services/loading-service/loading.service.spec.ts
index 3c5bc338c..697c94c01 100644
--- a/src/app/core/services/loading-service/loading.service.spec.ts
+++ b/src/app/core/services/loading-service/loading.service.spec.ts
@@ -45,7 +45,7 @@ describe('LoadingService (DONE)', () => {
it('... should return default false value', waitForAsync(() => {
loadingService.getLoadingStatus().subscribe({
next: (isLoading: boolean) => {
- expect(isLoading).toBeFalse();
+ expectToBe(isLoading, false);
},
});
}));
diff --git a/src/app/core/services/storage-service/storage.service.spec.ts b/src/app/core/services/storage-service/storage.service.spec.ts
index 79184cad8..eabf6fae1 100644
--- a/src/app/core/services/storage-service/storage.service.spec.ts
+++ b/src/app/core/services/storage-service/storage.service.spec.ts
@@ -67,7 +67,7 @@ describe('StorageService (DONE)', () => {
expectedStorage.removeItem('testkey');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
});
it('... should use correct mock storage', () => {
@@ -77,7 +77,7 @@ describe('StorageService (DONE)', () => {
expectedStorage.setItem('testkey', 'testvalue');
expectToBe(mockStorage.getItem('testkey'), 'testvalue');
- expect(otherMockStorage.getItem('testkey')).toBeNull();
+ expectToBe(otherMockStorage.getItem('testkey'), null);
mockStorage.clear();
otherMockStorage.clear();
@@ -85,7 +85,7 @@ describe('StorageService (DONE)', () => {
expectedOtherStorage.setItem('testkey', 'testvalue');
expectToBe(otherMockStorage.getItem('testkey'), 'testvalue');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
otherMockStorage.clear();
});
@@ -103,7 +103,7 @@ describe('StorageService (DONE)', () => {
expectedStorage.removeItem('testkey');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
});
it('... should remove the correct item', () => {
@@ -115,17 +115,17 @@ describe('StorageService (DONE)', () => {
expectedStorage.removeItem('testkey');
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
expectToBe(mockStorage.getItem('testkey2'), 'testvalue2');
expectedStorage.removeItem('testkey2');
- expect(mockStorage.getItem('testkey')).toBeNull();
- expect(mockStorage.getItem('testkey2')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
+ expectToBe(mockStorage.getItem('testkey2'), null);
});
it('... should clear mock storage after each run', () => {
- expect(mockStorage.getItem('testkey')).toBeNull();
+ expectToBe(mockStorage.getItem('testkey'), null);
});
});
@@ -135,7 +135,7 @@ describe('StorageService (DONE)', () => {
});
it('... should set a given key/item string pair to a given storage type', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
@@ -144,8 +144,8 @@ describe('StorageService (DONE)', () => {
it('... should set item to the correct storage type', () => {
const otherMockStorage = mockLocalStorage;
- expect(mockStorage.getItem(expectedKey)).toBeNull();
- expect(otherMockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
+ expectToBe(otherMockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, expectedKey, expectedItem);
storageService.setStorageKey(localType, expectedKey, otherItem);
@@ -157,14 +157,14 @@ describe('StorageService (DONE)', () => {
});
it('... should set a new key/item when a key does not exist', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
});
it('... should overwrite an existing item with the correct item when a key exists', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
@@ -175,55 +175,55 @@ describe('StorageService (DONE)', () => {
describe('... should do nothing if:', () => {
it('- storage type is undefined ', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(undefined, expectedKey, expectedItem);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('- storage type is null', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(null, expectedKey, expectedItem);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('- storage is not available', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
spyOn(storageService, '_storageIsAvailable').and.returnValue(false);
storageService.setStorageKey(sessionType, expectedKey, expectedItem);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('- storage is not supported', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
spyOn(storageService, '_storageIsSupported').and.returnValue(false);
storageService.setStorageKey(sessionType, expectedKey, expectedItem);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('- key is undefined ', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, undefined, expectedItem);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('- key is null', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, null, expectedItem);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('- value is undefined ', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, expectedKey, undefined);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('- value is null', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, expectedKey, null);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
});
});
@@ -234,7 +234,7 @@ describe('StorageService (DONE)', () => {
});
it('... should get an item by key from a given storage type', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectToBe(storageService.getStorageKey(sessionType, expectedKey), expectedItem);
@@ -244,8 +244,8 @@ describe('StorageService (DONE)', () => {
const expectedOtherStorage = expectedLocalStorage;
const otherMockStorage = mockLocalStorage;
- expect(mockStorage.getItem(expectedKey)).toBeNull();
- expect(otherMockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
+ expectToBe(otherMockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectedOtherStorage.setItem(expectedKey, otherItem);
@@ -257,50 +257,50 @@ describe('StorageService (DONE)', () => {
});
it('... should return null for non existing keys', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
- expect(storageService.getStorageKey(sessionType, expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
+ expectToBe(storageService.getStorageKey(sessionType, expectedKey), null);
});
describe('... should do nothing if:', () => {
it('- storage type is undefined ', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
- expect(storageService.getStorageKey(undefined, expectedKey)).toBeNull();
+ expectToBe(storageService.getStorageKey(undefined, expectedKey), null);
});
it('- storage type is null', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
- expect(storageService.getStorageKey(null, expectedKey)).toBeNull();
+ expectToBe(storageService.getStorageKey(null, expectedKey), null);
});
it('- storage has not the given key', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
spyOn(storageService, '_storageHasKey').and.returnValue(false);
- expect(storageService.getStorageKey(sessionType, expectedKey)).toBeNull();
+ expectToBe(storageService.getStorageKey(sessionType, expectedKey), null);
});
it('- storage is not supported', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
spyOn(storageService, '_storageIsSupported').and.returnValue(undefined);
- expect(storageService.getStorageKey(sessionType, expectedKey)).toBeNull();
+ expectToBe(storageService.getStorageKey(sessionType, expectedKey), null);
});
it('- storage is not available', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
spyOn(storageService, '_storageIsAvailable').and.returnValue(undefined);
- expect(storageService.getStorageKey(sessionType, expectedKey)).toBeNull();
+ expectToBe(storageService.getStorageKey(sessionType, expectedKey), null);
});
});
});
@@ -311,44 +311,44 @@ describe('StorageService (DONE)', () => {
});
it('... should remove an item by key from a given storage type', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
storageService.setStorageKey(sessionType, expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
storageService.removeStorageKey(sessionType, expectedKey);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
});
it('... should remove item from the correct storage type', () => {
const expectedOtherStorage = expectedLocalStorage;
const otherMockStorage = mockLocalStorage;
- expect(mockStorage.getItem(expectedKey)).toBeNull();
- expect(otherMockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
+ expectToBe(otherMockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectedOtherStorage.setItem(expectedKey, otherItem);
storageService.removeStorageKey(sessionType, expectedKey);
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectToBe(otherMockStorage.getItem(expectedKey), otherItem);
storageService.removeStorageKey(localType, expectedKey);
- expect(otherMockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(otherMockStorage.getItem(expectedKey), null);
otherMockStorage.clear();
});
it('... should return for non existing items', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expect(storageService.removeStorageKey(sessionType, expectedKey)).toBeUndefined();
});
describe('... should do nothing if:', () => {
it('- storage type is undefined ', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
@@ -359,7 +359,7 @@ describe('StorageService (DONE)', () => {
});
it('- storage type is null', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
@@ -370,7 +370,7 @@ describe('StorageService (DONE)', () => {
});
it('- storage has not the given key', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
@@ -382,7 +382,7 @@ describe('StorageService (DONE)', () => {
});
it('- storage is not supported', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectToBe(expectedStorage.getItem(expectedKey), expectedItem);
@@ -394,7 +394,7 @@ describe('StorageService (DONE)', () => {
});
it('- storage is not available', () => {
- expect(mockStorage.getItem(expectedKey)).toBeNull();
+ expectToBe(mockStorage.getItem(expectedKey), null);
expectedStorage.setItem(expectedKey, expectedItem);
expectToBe(mockStorage.getItem(expectedKey), expectedItem);
diff --git a/src/app/core/services/utility-service/utility.service.spec.ts b/src/app/core/services/utility-service/utility.service.spec.ts
index 389ae020e..1ec7d7b75 100644
--- a/src/app/core/services/utility-service/utility.service.spec.ts
+++ b/src/app/core/services/utility-service/utility.service.spec.ts
@@ -1,5 +1,7 @@
import { TestBed } from '@angular/core/testing';
+import { expectToBe } from '@testing/expect-helper';
+
import { UtilityService } from './utility.service';
describe('UtilityService (DONE)', () => {
@@ -24,22 +26,22 @@ describe('UtilityService (DONE)', () => {
it('... should return true if a given array is not empty', () => {
const checkArray = [1];
- expect(utils.isNotEmptyArray(checkArray)).toBeTrue();
+ expectToBe(utils.isNotEmptyArray(checkArray), true);
});
it('... should return false if a given array is empty', () => {
const checkArray = [];
- expect(utils.isNotEmptyArray(checkArray)).toBeFalse();
+ expectToBe(utils.isNotEmptyArray(checkArray), false);
});
it('... should return false if a given array is null', () => {
const checkArray = null;
- expect(utils.isNotEmptyArray(checkArray)).toBeFalse();
+ expectToBe(utils.isNotEmptyArray(checkArray), false);
});
it('... should return false if a given array is undefined', () => {
const checkArray = undefined;
- expect(utils.isNotEmptyArray(checkArray)).toBeFalse();
+ expectToBe(utils.isNotEmptyArray(checkArray), false);
});
});
@@ -50,32 +52,32 @@ describe('UtilityService (DONE)', () => {
it('... should return true if a given object is not empty', () => {
const checkObj = { a: 1 };
- expect(utils.isNotEmptyObject(checkObj)).toBeTrue();
+ expectToBe(utils.isNotEmptyObject(checkObj), true);
});
it('... should return false if a given object is empty', () => {
const checkObj = {};
- expect(utils.isNotEmptyObject(checkObj)).toBeFalse();
+ expectToBe(utils.isNotEmptyObject(checkObj), false);
});
it('... should return false if a given object is an Array', () => {
const checkObj = [1, 2, 3];
- expect(utils.isNotEmptyObject(checkObj)).toBeFalse();
+ expectToBe(utils.isNotEmptyObject(checkObj), false);
});
it('... should return false if a given object is an empty Array', () => {
const checkObj = [];
- expect(utils.isNotEmptyObject(checkObj)).toBeFalse();
+ expectToBe(utils.isNotEmptyObject(checkObj), false);
});
it('... should return false if a given object is undefined', () => {
const checkObj = undefined;
- expect(utils.isNotEmptyObject(checkObj)).toBeFalse();
+ expectToBe(utils.isNotEmptyObject(checkObj), false);
});
it('... should return false if a given object is null', () => {
const checkObj = null;
- expect(utils.isNotEmptyObject(checkObj)).toBeFalse();
+ expectToBe(utils.isNotEmptyObject(checkObj), false);
});
});
@@ -88,13 +90,13 @@ describe('UtilityService (DONE)', () => {
it('... id is undefined', () => {
const result = utils.isSketchId(undefined);
- expect(result).toBeFalse();
+ expectToBe(result, false);
});
it('... id is null', () => {
const result = utils.isSketchId(null);
- expect(result).toBeFalse();
+ expectToBe(result, false);
});
it('... id does not include `_Sk`', () => {
@@ -102,7 +104,7 @@ describe('UtilityService (DONE)', () => {
const result = utils.isSketchId(id);
- expect(result).toBeFalse();
+ expectToBe(result, false);
});
});
@@ -111,7 +113,7 @@ describe('UtilityService (DONE)', () => {
const result = utils.isSketchId(id);
- expect(result).toBeTrue();
+ expectToBe(result, true);
});
it('... should return true if id includes `SkRT`', () => {
@@ -119,7 +121,7 @@ describe('UtilityService (DONE)', () => {
const result = utils.isSketchId(id);
- expect(result).toBeTrue();
+ expectToBe(result, true);
});
});
});
diff --git a/src/app/core/view-container/view-container.component.spec.ts b/src/app/core/view-container/view-container.component.spec.ts
index 7560a8323..17a423c14 100644
--- a/src/app/core/view-container/view-container.component.spec.ts
+++ b/src/app/core/view-container/view-container.component.spec.ts
@@ -52,11 +52,10 @@ describe('ViewContainerComponent (DONE)', () => {
// Main outlet should not be named
expect(routletDes[0].attributes).toBeDefined();
- expect(routletDes[0].attributes['name']).not.toBeDefined();
+ expect(routletDes[0].attributes['name']).toBeUndefined();
// Secondary outlet should be named 'side'
expect(routletDes[1].attributes).toBeDefined();
- expect(routletDes[1].attributes['name']).toBeDefined();
expectToBe(routletDes[1].attributes['name'], 'side');
});
});
diff --git a/src/app/shared/address/address.component.spec.ts b/src/app/shared/address/address.component.spec.ts
index 8e6e5ba67..f80c15595 100644
--- a/src/app/shared/address/address.component.spec.ts
+++ b/src/app/shared/address/address.component.spec.ts
@@ -2,7 +2,7 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
-import { getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectToBe, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { METADATA } from '@awg-core/core-data';
import { MetaContact, MetaPage, MetaSectionTypes } from '@awg-core/core-models';
@@ -63,11 +63,8 @@ describe('AddressComponent (DONE)', () => {
const headerDes = getAndExpectDebugElementByCss(compDe, 'address p#awg-address-header a', 1, 1);
const headerEl = headerDes[0].nativeElement;
- expect(headerEl.href).toBeDefined();
- expect(headerEl.href).toBeFalsy();
-
- expect(headerEl.textContent).toBeDefined();
- expect(headerEl.textContent).toBeFalsy();
+ expectToBe(headerEl.href, '');
+ expectToBe(headerEl.textContent, '');
});
it('... should not render the address content information yet', () => {
@@ -93,25 +90,14 @@ describe('AddressComponent (DONE)', () => {
const phoneEl = phoneDes[0].nativeElement;
const emailEl = emailDes[0].nativeElement;
- expect(institutionEl.textContent).toBeDefined();
- expect(institutionEl.textContent).toBeFalsy();
-
- expect(streetEl.textContent).toBeDefined();
- expect(streetEl.textContent).toBeFalsy();
-
- expect(postalCityEl.textContent).toBeDefined();
- expect(postalCityEl.textContent).toBeFalsy();
+ expectToBe(institutionEl.textContent, '');
+ expectToBe(streetEl.textContent, '');
+ expectToBe(postalCityEl.textContent, '');
+ expectToBe(countryEl.textContent, '');
- expect(countryEl.textContent).toBeDefined();
- expect(countryEl.textContent).toBeFalsy();
-
- expect(phoneEl.textContent).toBeDefined();
- expect(phoneEl.textContent).toBeFalsy();
-
- expect(emailEl.href).toBeDefined();
- expect(emailEl.href).toBeFalsy();
- expect(emailEl.textContent).toBeDefined();
- expect(emailEl.textContent).toBeFalsy();
+ expectToBe(phoneEl.textContent, '');
+ expectToBe(emailEl.href, '');
+ expectToBe(emailEl.textContent, '');
});
});
});
@@ -131,15 +117,8 @@ describe('AddressComponent (DONE)', () => {
const headerDes = getAndExpectDebugElementByCss(compDe, 'address p#awg-address-header a', 1, 1);
const headerEl = headerDes[0].nativeElement;
- expect(headerEl.href).toBeTruthy();
- expect(headerEl.href)
- .withContext(`should be ${expectedPageMetaData.awgProjectUrl}`)
- .toBe(expectedPageMetaData.awgProjectUrl);
-
- expect(headerEl.textContent).toBeTruthy();
- expect(headerEl.textContent)
- .withContext(`should be ${expectedPageMetaData.awgProjectName}`)
- .toBe(expectedPageMetaData.awgProjectName);
+ expectToBe(headerEl.href, expectedPageMetaData.awgProjectUrl);
+ expectToBe(headerEl.textContent, expectedPageMetaData.awgProjectName);
});
it('... should render the address content institution information', () => {
@@ -151,10 +130,7 @@ describe('AddressComponent (DONE)', () => {
);
const institutionEl = institutionDes[0].nativeElement;
- expect(institutionEl.textContent).toBeTruthy();
- expect(institutionEl.textContent)
- .withContext(`should be ${expectedContactMetaData.address.institution}`)
- .toBe(expectedContactMetaData.address.institution);
+ expectToBe(institutionEl.textContent, expectedContactMetaData.address.institution);
});
it('... should render the address content street information', () => {
@@ -166,10 +142,7 @@ describe('AddressComponent (DONE)', () => {
);
const streetEl = streetDes[0].nativeElement;
- expect(streetEl.textContent).toBeTruthy();
- expect(streetEl.textContent)
- .withContext(`should be ${expectedContactMetaData.address.street}`)
- .toBe(expectedContactMetaData.address.street);
+ expectToBe(streetEl.textContent, expectedContactMetaData.address.street);
});
it('... should render the address content postal city information', () => {
@@ -184,10 +157,7 @@ describe('AddressComponent (DONE)', () => {
const expectedPostalCity =
expectedContactMetaData.address.postalCode + '\xA0' + expectedContactMetaData.address.city;
- expect(postalCityEl.textContent).toBeTruthy();
- expect(postalCityEl.textContent)
- .withContext(`should be ${expectedPostalCity}`)
- .toBe(expectedPostalCity);
+ expectToBe(postalCityEl.textContent, expectedPostalCity);
});
it('... should render the address content country information', () => {
@@ -199,10 +169,7 @@ describe('AddressComponent (DONE)', () => {
);
const countryEl = countryDes[0].nativeElement;
- expect(countryEl.textContent).toBeTruthy();
- expect(countryEl.textContent)
- .withContext(`should be ${expectedContactMetaData.address.country}`)
- .toBe(expectedContactMetaData.address.country);
+ expectToBe(countryEl.textContent, expectedContactMetaData.address.country);
});
it('... should render the address content phone information', () => {
@@ -217,8 +184,7 @@ describe('AddressComponent (DONE)', () => {
const expectedPhone =
expectedContactMetaData.phone.label + '\xA0' + expectedContactMetaData.phone.number;
- expect(phoneEl.textContent).toBeTruthy();
- expect(phoneEl.textContent).withContext(`should be ${expectedPhone}`).toBe(expectedPhone);
+ expectToBe(phoneEl.textContent, expectedPhone);
});
it('... should render the address content email information', () => {
@@ -230,14 +196,8 @@ describe('AddressComponent (DONE)', () => {
);
const emailEl = emailDes[0].nativeElement;
- expect(emailEl.href).toBeTruthy();
- expect(emailEl.href)
- .withContext(`should be ${expectedContactMetaData.email.mailto}`)
- .toBe(expectedContactMetaData.email.mailto);
- expect(emailEl.textContent).toBeTruthy();
- expect(emailEl.textContent)
- .withContext(`should be ${expectedContactMetaData.email.safeString}`)
- .toBe(expectedContactMetaData.email.safeString);
+ expectToBe(emailEl.href, expectedContactMetaData.email.mailto);
+ expectToBe(emailEl.textContent, expectedContactMetaData.email.safeString);
});
});
});
diff --git a/src/app/shared/codemirror/codemirror.component.spec.ts b/src/app/shared/codemirror/codemirror.component.spec.ts
index 7b56ea822..1f61cbf16 100644
--- a/src/app/shared/codemirror/codemirror.component.spec.ts
+++ b/src/app/shared/codemirror/codemirror.component.spec.ts
@@ -8,7 +8,7 @@ import { sparql } from '@codemirror/legacy-modes/mode/sparql';
import { EditorState, EditorStateConfig, Extension } from '@codemirror/state';
import { basicSetup } from 'codemirror';
-import { expectSpyCall, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { CmMode, CodeMirrorComponent } from './codemirror.component';
@@ -70,7 +70,7 @@ describe('CodemirrorComponent', () => {
describe('VIEW', () => {
it('... should contain one div.codemirrorhost', () => {
// Div debug element
- const accordionDes = getAndExpectDebugElementByCss(compDe, 'div.codemirrorhost', 1, 1);
+ getAndExpectDebugElementByCss(compDe, 'div.codemirrorhost', 1, 1);
});
});
});
@@ -86,13 +86,11 @@ describe('CodemirrorComponent', () => {
});
it('... should have mode', () => {
- expect(component.mode).toBeDefined();
- expect(component.mode).withContext(`should equal ${expectedMode}`).toEqual(expectedMode);
+ expectToEqual(component.mode, expectedMode);
});
it('... should have content', () => {
- expect(component.content).toBeDefined();
- expect(component.content).withContext(`should equal ${expectedContent}`).toEqual(expectedContent);
+ expectToBe(component.content, expectedContent);
});
describe('#init()', () => {
@@ -111,17 +109,13 @@ describe('CodemirrorComponent', () => {
fixture.detectChanges();
expectSpyCall(initSpy, 2, expectedState);
- expect(component.editor.state).toBeDefined();
- expect(component.editor.state).withContext(`should equal ${expectedState}`).toEqual(expectedState);
+ expectToEqual(component.editor.state, expectedState);
});
it('... should init the editor with the correct content if given', () => {
expectSpyCall(initSpy, 1);
- expect(component.editor.state.doc.toString()).toBeDefined();
- expect(component.editor.state.doc.toString())
- .withContext(`should equal ${expectedContent}`)
- .toEqual(expectedContent);
+ expectToBe(component.editor.state.doc.toString(), expectedContent);
});
it('... should init an empty editor if no content is given', () => {
@@ -132,8 +126,7 @@ describe('CodemirrorComponent', () => {
fixture.detectChanges();
expectSpyCall(initSpy, 1);
- expect(component.editor.state.doc.toString()).toBeDefined();
- expect(component.editor.state.doc.toString()).withContext(`should equal ''`).toEqual('');
+ expectToBe(component.editor.state.doc.toString(), '');
});
});
diff --git a/src/app/shared/error-alert/error-alert.component.html b/src/app/shared/error-alert/error-alert.component.html
new file mode 100644
index 000000000..b305535d4
--- /dev/null
+++ b/src/app/shared/error-alert/error-alert.component.html
@@ -0,0 +1,5 @@
+
+
+
{{ errorObject | json }}
+
+
diff --git a/src/app/views/edition-view/edition-outlets/edition-type/edition-type.component.scss b/src/app/shared/error-alert/error-alert.component.scss
similarity index 100%
rename from src/app/views/edition-view/edition-outlets/edition-type/edition-type.component.scss
rename to src/app/shared/error-alert/error-alert.component.scss
diff --git a/src/app/shared/error-alert/error-alert.component.spec.ts b/src/app/shared/error-alert/error-alert.component.spec.ts
new file mode 100644
index 000000000..8268c9f27
--- /dev/null
+++ b/src/app/shared/error-alert/error-alert.component.spec.ts
@@ -0,0 +1,77 @@
+import { JsonPipe } from '@angular/common';
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { expectToBe, expectToContain, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+
+import { ErrorAlertComponent } from './error-alert.component';
+
+describe('ErrorAlertComponent', () => {
+ let component: ErrorAlertComponent;
+ let fixture: ComponentFixture;
+ let compDe: DebugElement;
+
+ let expectedErrorObject: any;
+
+ const jsonPipe = new JsonPipe();
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ErrorAlertComponent],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ErrorAlertComponent);
+ component = fixture.componentInstance;
+ compDe = fixture.debugElement;
+
+ // Test data
+ expectedErrorObject = { status: 404, statusText: 'got Error' };
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('BEFORE initial data binding', () => {
+ it('... should not have `errorObject`', () => {
+ expect(component.errorObject).toBeUndefined();
+ });
+
+ describe('VIEW', () => {
+ it('... should have an outer div.awg-error-message', () => {
+ getAndExpectDebugElementByCss(compDe, 'div.awg-error-message', 1, 1);
+ });
+
+ it('... should have a centered danger alert in div.awg-error-message', () => {
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div.awg-error-message ', 1, 1);
+
+ getAndExpectDebugElementByCss(divDes[0], 'div.text-center > div.alert-danger', 1, 1);
+ });
+
+ it('... should not display an error message in div.alert yet', () => {
+ const alertDes = getAndExpectDebugElementByCss(compDe, 'div.alert-danger', 1, 1);
+ const alertEl = alertDes[0].nativeElement;
+
+ expectToBe(alertEl.textContent, '');
+ });
+ });
+ });
+
+ describe('AFTER initial data binding', () => {
+ beforeEach(() => {
+ component.errorObject = expectedErrorObject;
+
+ // Trigger initial data binding
+ fixture.detectChanges();
+ });
+
+ describe('VIEW', () => {
+ it('... should display an error message in div.alert', () => {
+ const alertDes = getAndExpectDebugElementByCss(compDe, 'div.alert-danger', 1, 1);
+ const alertEl = alertDes[0].nativeElement;
+
+ expectToContain(alertEl.textContent, jsonPipe.transform(expectedErrorObject));
+ });
+ });
+ });
+});
diff --git a/src/app/shared/error-alert/error-alert.component.ts b/src/app/shared/error-alert/error-alert.component.ts
new file mode 100644
index 000000000..ad74ea9bd
--- /dev/null
+++ b/src/app/shared/error-alert/error-alert.component.ts
@@ -0,0 +1,22 @@
+import { Component, Input } from '@angular/core';
+
+/**
+ * The ErrorAlertComponent.
+ *
+ * It contains an error alert message that is
+ * provided via the {@link SharedModule}.
+ */
+@Component({
+ selector: 'awg-error-alert',
+ templateUrl: './error-alert.component.html',
+ styleUrl: './error-alert.component.scss',
+})
+export class ErrorAlertComponent {
+ /**
+ * Input variable: errorObject.
+ *
+ * It keeps the error object for the component.
+ */
+ @Input()
+ errorObject: any;
+}
diff --git a/src/app/shared/external-link/external-link.directive.spec.ts b/src/app/shared/external-link/external-link.directive.spec.ts
index 4785c1212..2a7483351 100644
--- a/src/app/shared/external-link/external-link.directive.spec.ts
+++ b/src/app/shared/external-link/external-link.directive.spec.ts
@@ -4,6 +4,7 @@ import { By } from '@angular/platform-browser';
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
+import { expectToBe } from '@testing/expect-helper';
import { ExternalLinkDirective } from './external-link.directive';
@Component({
@@ -63,47 +64,33 @@ describe('ExternalLinkDirective', () => {
// All elements with an attached ExternalLinkDirective (a[href])
aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
- expect(aDes).toBeDefined();
- expect(aDes.length).withContext('should be 4').toBe(4);
+ expectToBe(aDes.length, 4);
});
it('... should have 1 anchor element without href attributes', () => {
bareADes = fixture.debugElement.queryAll(By.css('a:not([href])'));
- expect(bareADes).toBeDefined();
- expect(bareADes.length).withContext('should be 1').toBe(1);
+ expectToBe(bareADes.length, 1);
});
it('... should apply [href|target|rel] values to 1st anchor element (external)', () => {
aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
const aEl = aDes[0].nativeElement;
- expect(aEl.href).toBeTruthy();
- expect(aEl.href).withContext(`should be ${expectedExternalLink}`).toBe(expectedExternalLink);
-
- expect(aEl.rel).toBeTruthy();
- expect(aEl.rel).withContext(`should be ${expectedRelAttr}`).toBe(expectedRelAttr);
-
- expect(aEl.target).toBeTruthy();
- expect(aEl.target).withContext(`should be ${expectedTargetAttr}`).toBe(expectedTargetAttr);
-
- expect(aEl.innerText).withContext('should be "Link External"').toBe('Link External');
+ expectToBe(aEl.href, expectedExternalLink);
+ expectToBe(aEl.rel, expectedRelAttr);
+ expectToBe(aEl.target, expectedTargetAttr);
+ expectToBe(aEl.innerText, 'Link External');
});
it('... should apply [href|target|rel] values to 2nd anchor element (dynamic external)', () => {
aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
const aEl = aDes[1].nativeElement;
- expect(aEl.href).toBeTruthy();
- expect(aEl.href).withContext(`should be ${expectedExternalLink}`).toBe(expectedExternalLink);
-
- expect(aEl.rel).toBeTruthy();
- expect(aEl.rel).withContext(`should be ${expectedRelAttr}`).toBe(expectedRelAttr);
-
- expect(aEl.target).toBeTruthy();
- expect(aEl.target).withContext(`should be ${expectedTargetAttr}`).toBe(expectedTargetAttr);
-
- expect(aEl.innerText).withContext('should be "Link External Dynamic"').toBe('Link External Dynamic');
+ expectToBe(aEl.href, expectedExternalLink);
+ expectToBe(aEl.rel, expectedRelAttr);
+ expectToBe(aEl.target, expectedTargetAttr);
+ expectToBe(aEl.innerText, 'Link External Dynamic');
});
it('... should not apply [target|rel] values to 3rd anchor element (internal)', () => {
@@ -112,13 +99,10 @@ describe('ExternalLinkDirective', () => {
const expectedHref = aEl.baseURI + aEl.hostname + expectedInternalLink;
- expect(aEl.href).toBeTruthy();
- expect(aEl.href).withContext(`should be ${expectedHref}`).toBe(expectedHref);
-
- expect(aEl.rel).withContext('should be empty string').not.toBeTruthy();
- expect(aEl.target).withContext('should be empty string').not.toBeTruthy();
-
- expect(aEl.innerText).withContext('should be "Link Internal"').toBe('Link Internal');
+ expectToBe(aEl.href, expectedHref);
+ expectToBe(aEl.rel, '');
+ expectToBe(aEl.target, '');
+ expectToBe(aEl.innerText, 'Link Internal');
});
it('... should not apply [target|rel] values to 4th anchor element (dynamic internal)', () => {
@@ -127,24 +111,19 @@ describe('ExternalLinkDirective', () => {
const expectedHref = aEl.baseURI + aEl.hostname + expectedInternalLink;
- expect(aEl.href).toBeTruthy();
- expect(aEl.href).withContext(`should be ${expectedHref}`).toBe(expectedHref);
-
- expect(aEl.rel).withContext('should be empty string').not.toBeTruthy();
- expect(aEl.target).withContext('should be empty string').not.toBeTruthy();
-
- expect(aEl.innerText).withContext('should be "Link Internal Dynamic"').toBe('Link Internal Dynamic');
+ expectToBe(aEl.href, expectedHref);
+ expectToBe(aEl.rel, '');
+ expectToBe(aEl.target, '');
+ expectToBe(aEl.innerText, 'Link Internal Dynamic');
});
it('... should not apply [href|target|rel] values to bare anchor', () => {
bareADes = fixture.debugElement.queryAll(By.css('a:not([href])'));
- expect(bareADes[0].properties['href']).withContext('should be empty string').not.toBeTruthy();
- expect(bareADes[0].properties['target']).withContext('should be empty string').not.toBeTruthy();
- expect(bareADes[0].properties['rel']).withContext('should be empty string').not.toBeTruthy();
- expect(bareADes[0].properties['innerText'])
- .withContext('should be "Link without href"')
- .toBe('Link without href');
+ expectToBe(bareADes[0].properties['href'], '');
+ expectToBe(bareADes[0].properties['target'], '');
+ expectToBe(bareADes[0].properties['rel'], '');
+ expectToBe(bareADes[0].properties['innerText'], 'Link without href');
});
it('... should reflect input change for [href] values', () => {
@@ -156,15 +135,9 @@ describe('ExternalLinkDirective', () => {
aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
const aEl = aDes[1].nativeElement;
- expect(aEl.href).toBeTruthy();
- expect(aEl.href).withContext(`should be ${expectedNewExternalLink}`).toBe(expectedNewExternalLink);
-
- expect(aEl.rel).toBeTruthy();
- expect(aEl.rel).withContext(`should be ${expectedRelAttr}`).toBe(expectedRelAttr);
-
- expect(aEl.target).toBeTruthy();
- expect(aEl.target).withContext(`should be ${expectedTargetAttr}`).toBe(expectedTargetAttr);
-
- expect(aEl.innerText).withContext('should be "Link External Dynamic"').toBe('Link External Dynamic');
+ expectToBe(aEl.href, expectedNewExternalLink);
+ expectToBe(aEl.rel, expectedRelAttr);
+ expectToBe(aEl.target, expectedTargetAttr);
+ expectToBe(aEl.innerText, 'Link External Dynamic');
});
});
diff --git a/src/app/shared/heading/heading.component.spec.ts b/src/app/shared/heading/heading.component.spec.ts
index dbd47d027..a661e61c3 100644
--- a/src/app/shared/heading/heading.component.spec.ts
+++ b/src/app/shared/heading/heading.component.spec.ts
@@ -3,7 +3,7 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
-import { getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectToContain, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { HeadingComponent } from './heading.component';
@@ -71,11 +71,8 @@ describe('HeadingComponent (DONE)', () => {
const divEl = divDes[0].nativeElement;
const headerEl = headerDes[0].nativeElement;
- expect(divEl.id).toBeDefined();
- expect(divEl.id).withContext(`should contain ${expectedId}`).toContain(expectedId);
-
- expect(headerEl.textContent).toBeDefined();
- expect(headerEl.textContent).withContext(`should contain ${expectedTitle}`).toContain(expectedTitle);
+ expectToContain(divEl.id, expectedId);
+ expectToContain(headerEl.textContent, expectedTitle);
});
});
});
diff --git a/src/app/shared/json-viewer/json-viewer.component.spec.ts b/src/app/shared/json-viewer/json-viewer.component.spec.ts
index df6888eec..972e0578c 100644
--- a/src/app/shared/json-viewer/json-viewer.component.spec.ts
+++ b/src/app/shared/json-viewer/json-viewer.component.spec.ts
@@ -6,7 +6,13 @@ import { By } from '@angular/platform-browser';
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { click } from '@testing/click-helper';
import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
-import { getAndExpectDebugElementByCss, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import {
+ expectToBe,
+ expectToContain,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+ getAndExpectDebugElementByDirective,
+} from '@testing/expect-helper';
import { NgbConfig, NgbNavLink, NgbNavModule, NgbNavOutlet } from '@ng-bootstrap/ng-bootstrap';
@@ -131,24 +137,20 @@ describe('JsonViewerComponent (DONE)', () => {
getAndExpectDebugElementByCss(bodyDe[0], 'nav[ngbNav]', 1, 1);
const navLinkDes = getNavLinks(fixture);
- expect(navLinkDes).toBeTruthy();
- expect(navLinkDes.length).withContext('should have 2 navLinks').toBe(2);
+ expectToBe(navLinkDes.length, 2);
});
it('... should have one Formatted and one Plain navItem and display titles', () => {
const navLinks = getNavLinks(fixture);
- expect(navLinks[0].textContent).toBeTruthy();
- expect(navLinks[0].textContent).withContext(`should be 'Formatted'`).toBe('Formatted');
-
- expect(navLinks[1].textContent).toBeTruthy();
- expect(navLinks[1].textContent).withContext(`should be 'Plain'`).toBe('Plain');
+ expectToBe(navLinks[0].textContent, 'Formatted');
+ expectToBe(navLinks[1].textContent, 'Plain');
});
it('... should not render navItem content yet', () => {
const navContent = getNavContents(fixture);
- expect(navContent.length).withContext(`should be 0`).toBe(0);
+ expectToBe(navContent.length, 0);
});
it('... should not contain ngx-json-viewer component (stubbed)', () => {
@@ -171,7 +173,7 @@ describe('JsonViewerComponent (DONE)', () => {
it('... should render navItem content and select first navItem (Formatted) by default', () => {
const navContent = getNavContents(fixture);
- expect(navContent.length).toBe(1);
+ expectToBe(navContent.length, 1);
expectNavPanel(fixture, [true, false], ['content1']);
});
@@ -211,8 +213,7 @@ describe('JsonViewerComponent (DONE)', () => {
const viewerDes = getAndExpectDebugElementByDirective(compDe, NgxJsonViewerStubComponent, 1, 0);
const viewerCmp = viewerDes[0].injector.get(NgxJsonViewerStubComponent) as NgxJsonViewerStubComponent;
- expect(viewerCmp.json).toBeDefined();
- expect(viewerCmp.json).withContext(`should equal: ${expectedData}`).toEqual(expectedData);
+ expectToEqual(viewerCmp.json, expectedData);
});
it('... should render `jsonViewerData` in Plain view', async () => {
@@ -227,9 +228,8 @@ describe('JsonViewerComponent (DONE)', () => {
const jsonPipe = new JsonPipe();
const pipedData = jsonPipe.transform(expectedData);
- expect(navContent.length).withContext('should be 1').toBe(1);
- expect(navContent[0].textContent).toBeTruthy();
- expect(navContent[0].textContent).withContext(`should contain ${pipedData}`).toContain(pipedData);
+ expectToBe(navContent.length, 1);
+ expectToContain(navContent[0].textContent, pipedData);
});
});
});
diff --git a/src/app/shared/modal/modal.component.spec.ts b/src/app/shared/modal/modal.component.spec.ts
index da1162c02..124a2c83d 100644
--- a/src/app/shared/modal/modal.component.spec.ts
+++ b/src/app/shared/modal/modal.component.spec.ts
@@ -6,7 +6,7 @@ import { ModalDismissReasons, NgbModal, NgbModalModule } from '@ng-bootstrap/ng-
import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
-import { expectSpyCall, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { CompileHtmlComponent } from '@awg-shared/compile-html';
@@ -102,21 +102,16 @@ describe('ModalComponent', () => {
});
it('... should have modal title', () => {
- expect(component.modalTitle).toBeDefined();
- expect(component.modalTitle).withContext(`should be ${expectedModalTitle}`).toBe(expectedModalTitle);
+ expectToBe(component.modalTitle, expectedModalTitle);
});
it('... should have modal close label', () => {
- expect(component.modalCloseLabel).toBeDefined();
- expect(component.modalCloseLabel)
- .withContext(`should be ${expectedModalCloseLabel}`)
- .toBe(expectedModalCloseLabel);
+ expectToBe(component.modalCloseLabel, expectedModalCloseLabel);
});
it('... should recognize the modal template', () => {
- expect(component.modalTemplate).toBeDefined();
- expect(component.modalTemplate).withContext(`should be a TemplateRef`).toBeInstanceOf(TemplateRef);
- expect(component.modalTemplate).withContext(`should be a wrapperComponent.modal`).toBe(wrapperComponent.modal);
+ expectToBe(component.modalTemplate, wrapperComponent.modal);
+ expect(component.modalTemplate).toBeInstanceOf(TemplateRef);
});
it('... should recognize the modal template in wrapper component', () => {
@@ -146,8 +141,7 @@ describe('ModalComponent', () => {
const titleDes = getAndExpectDebugElementByCss(headerDes[0], 'h4.modal-title', 1, 1);
const titleEl = titleDes[0].nativeElement;
- expect(titleEl).toBeDefined();
- expect(titleEl.textContent).withContext(`should be ${expectedModalTitle}`).toBe(expectedModalTitle);
+ expectToBe(titleEl.textContent, expectedModalTitle);
});
it('... should have close button without label in div.modal-header', () => {
@@ -155,8 +149,7 @@ describe('ModalComponent', () => {
const buttonDes = getAndExpectDebugElementByCss(headerDes[0], 'button.btn-close', 1, 1);
const buttonEl = buttonDes[0].nativeElement;
- expect(buttonEl).toBeDefined();
- expect(buttonEl.textContent).withContext(`should be ''`).toBe('');
+ expectToBe(buttonEl.textContent, '');
});
it('... should have one div.modal-body', () => {
@@ -174,10 +167,7 @@ describe('ModalComponent', () => {
const htmlSnippet = mockDocument.createElement('p');
htmlSnippet.innerHTML = EXPECTED_MODAL_CONTENT_SNIPPETS[expectedSnippetKey1];
- expect(bodyEl).toBeDefined();
- expect(bodyEl.textContent.trim())
- .withContext(`should be ${htmlSnippet.textContent.trim()}`)
- .toBe(htmlSnippet.textContent.trim());
+ expectToBe(bodyEl.textContent.trim(), htmlSnippet.textContent.trim());
});
it('... should have one div.modal-footer', () => {
@@ -194,10 +184,7 @@ describe('ModalComponent', () => {
const buttonDes = getAndExpectDebugElementByCss(footerDes[0], 'button.awg-modal-button', 1, 1);
const buttonEl = buttonDes[0].nativeElement;
- expect(buttonEl).toBeDefined();
- expect(buttonEl.textContent.trim())
- .withContext(`should be ${expectedModalCloseLabel}`)
- .toBe(expectedModalCloseLabel);
+ expectToBe(buttonEl.textContent.trim(), expectedModalCloseLabel);
});
});
@@ -217,26 +204,19 @@ describe('ModalComponent', () => {
});
it('... should set the correct modal content if snippet is known', () => {
- expect(component.modalContent).toBeDefined();
- expect(component.modalContent)
- .withContext(` should be ${EXPECTED_MODAL_CONTENT_SNIPPETS[expectedSnippetKey1]}`)
- .toBe(EXPECTED_MODAL_CONTENT_SNIPPETS[expectedSnippetKey1]);
+ expectToBe(component.modalContent, EXPECTED_MODAL_CONTENT_SNIPPETS[expectedSnippetKey1]);
component.open(expectedSnippetKey2);
fixture.detectChanges();
- expect(component.modalContent).toBeDefined();
- expect(component.modalContent)
- .withContext(` should be ${EXPECTED_MODAL_CONTENT_SNIPPETS[expectedSnippetKey2]}`)
- .toBe(EXPECTED_MODAL_CONTENT_SNIPPETS[expectedSnippetKey2]);
+ expectToBe(component.modalContent, EXPECTED_MODAL_CONTENT_SNIPPETS[expectedSnippetKey2]);
});
it('... should set the modal content to empty string if snippet is unknown', () => {
component.open(expectedUnknownSnippetKey);
fixture.detectChanges();
- expect(component.modalContent).toBeDefined();
- expect(component.modalContent).withContext(`should be empty string`).toBe('');
+ expectToBe(component.modalContent, '');
});
it('... should return the close result of the modal', async () => {
@@ -251,8 +231,7 @@ describe('ModalComponent', () => {
ngbModal.open(component.modalTemplate, { ariaLabelledBy: 'awg-modal' }).result
).toBeResolvedTo(closeMessage);
- expect(component.closeResult).toBeDefined();
- expect(component.closeResult).toBe(expectedCloseResult);
+ expectToBe(component.closeResult, expectedCloseResult);
});
describe('should return the dismiss reason of the modal', async () => {
@@ -268,10 +247,7 @@ describe('ModalComponent', () => {
ngbModal.open(component.modalTemplate, { ariaLabelledBy: 'awg-modal' }).result
).toBeRejectedWith(dismissEvent);
- expect(component.closeResult).toBeDefined();
- expect(component.closeResult)
- .withContext(`should be ${expectedDismissReason}`)
- .toBe(expectedDismissReason);
+ expectToBe(component.closeResult, expectedDismissReason);
});
it('... when pressing ESC key', async () => {
@@ -286,10 +262,7 @@ describe('ModalComponent', () => {
ngbModal.open(component.modalTemplate, { ariaLabelledBy: 'awg-modal' }).result
).toBeRejectedWith(dismissEvent);
- expect(component.closeResult).toBeDefined();
- expect(component.closeResult)
- .withContext(`should be ${expectedDismissReason}`)
- .toBe(expectedDismissReason);
+ expectToBe(component.closeResult, expectedDismissReason);
});
it('... when clicking on backdrop', async () => {
@@ -304,10 +277,7 @@ describe('ModalComponent', () => {
ngbModal.open(component.modalTemplate, { ariaLabelledBy: 'awg-modal' }).result
).toBeRejectedWith(dismissEvent);
- expect(component.closeResult).toBeDefined();
- expect(component.closeResult)
- .withContext(`should be ${expectedDismissReason}`)
- .toBe(expectedDismissReason);
+ expectToBe(component.closeResult, expectedDismissReason);
});
});
});
diff --git a/src/app/shared/open-street-map/open-street-map.component.spec.ts b/src/app/shared/open-street-map/open-street-map.component.spec.ts
index a6e8c796d..7c19c5ccb 100644
--- a/src/app/shared/open-street-map/open-street-map.component.spec.ts
+++ b/src/app/shared/open-street-map/open-street-map.component.spec.ts
@@ -104,16 +104,14 @@ describe('OpenStreetMapComponent (DONE)', () => {
const mapDes = getAndExpectDebugElementByCss(compDe, 'iframe#awg-osm-embed-map', 1, 1);
const mapEl = mapDes[0].nativeElement;
- expect(mapEl.src).toBeDefined();
- expect(mapEl.src).toBeFalsy();
+ expectToBe(mapEl.src, '');
});
it('... should not have the link to OSM homepage yet', () => {
const linkDes = getAndExpectDebugElementByCss(compDe, 'div#awg-osm-link a', 1, 1);
const linkEl = linkDes[0].nativeElement;
- expect(linkEl.href).toBeDefined();
- expect(linkEl.href).toBeFalsy();
+ expectToBe(linkEl.href, '');
});
});
});
diff --git a/src/app/shared/order-by-pipe/order-by.pipe.spec.ts b/src/app/shared/order-by-pipe/order-by.pipe.spec.ts
index 39c4b051a..ce8ae372c 100644
--- a/src/app/shared/order-by-pipe/order-by.pipe.spec.ts
+++ b/src/app/shared/order-by-pipe/order-by.pipe.spec.ts
@@ -390,13 +390,14 @@ describe('OrderByPipe (DONE)', () => {
const parse = value => parseInt(value.replace(/[^0-9]/g, ''), 10);
- expect(
+ expectToEqual(
pipe.transform(arr, null, false, true, (a, b) => {
const newA = parse(a);
const newB = parse(b);
return newA > newB ? 1 : -1;
- })
- ).toEqual(res);
+ }),
+ res
+ );
});
describe('test not valid values for comparator', () => {
diff --git a/src/app/shared/router-link-button-group/router-link-button-group.component.spec.ts b/src/app/shared/router-link-button-group/router-link-button-group.component.spec.ts
index aaab3302d..40e3a4722 100644
--- a/src/app/shared/router-link-button-group/router-link-button-group.component.spec.ts
+++ b/src/app/shared/router-link-button-group/router-link-button-group.component.spec.ts
@@ -203,7 +203,7 @@ describe('RouterLinkButtonGroupComponent (DONE)', () => {
const fulltextLinkDe = linkDes[0]; // Fulltext link DebugElement
const fulltextLink = routerLinks[0]; // Fulltext link directive
- expect(fulltextLink.navigatedTo).toBeNull();
+ expectToBe(fulltextLink.navigatedTo, null);
click(fulltextLinkDe);
fixture.detectChanges();
@@ -216,7 +216,7 @@ describe('RouterLinkButtonGroupComponent (DONE)', () => {
const linkDe = linkDes[index];
const expectedRouterLink = expectedOrderOfRouterlinks[index];
- expect(routerLink.navigatedTo).toBeNull();
+ expectToBe(routerLink.navigatedTo, null);
click(linkDe);
fixture.detectChanges();
diff --git a/src/app/shared/scroll-to-top/scroll-to-top.component.html b/src/app/shared/scroll-to-top/scroll-to-top.component.html
new file mode 100644
index 000000000..5f6a3b49a
--- /dev/null
+++ b/src/app/shared/scroll-to-top/scroll-to-top.component.html
@@ -0,0 +1,5 @@
+@if (isScrolled) {
+
+}
diff --git a/src/app/shared/scroll-to-top/scroll-to-top.component.scss b/src/app/shared/scroll-to-top/scroll-to-top.component.scss
new file mode 100644
index 000000000..9a2d5a5ae
--- /dev/null
+++ b/src/app/shared/scroll-to-top/scroll-to-top.component.scss
@@ -0,0 +1,13 @@
+.awg-scroll-to-top {
+ position: fixed;
+ bottom: 30px;
+ right: 30px;
+ text-align: right;
+ color: white;
+ z-index: 1000;
+
+ &:hover {
+ cursor: pointer;
+ color: #f0f0f0;
+ }
+}
diff --git a/src/app/shared/scroll-to-top/scroll-to-top.component.spec.ts b/src/app/shared/scroll-to-top/scroll-to-top.component.spec.ts
new file mode 100644
index 000000000..bd4b83a47
--- /dev/null
+++ b/src/app/shared/scroll-to-top/scroll-to-top.component.spec.ts
@@ -0,0 +1,198 @@
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
+
+import Spy = jasmine.Spy;
+
+import { FontAwesomeTestingModule } from '@fortawesome/angular-fontawesome/testing';
+import { faArrowUp, IconDefinition } from '@fortawesome/free-solid-svg-icons';
+
+import { cleanStylesFromDOM } from '@testing/clean-up-helper';
+import { clickAndAwaitChanges } from '@testing/click-helper';
+import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
+import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+
+import { ScrollToTopComponent } from './scroll-to-top.component';
+
+describe('ScrollToTopComponent (DONE)', () => {
+ let component: ScrollToTopComponent;
+ let fixture: ComponentFixture;
+ let compDe: DebugElement;
+
+ let scrollToTopSpy: Spy;
+
+ let expectedScrollThreshold: number;
+ let expectedArrowIcon: IconDefinition;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ imports: [FontAwesomeTestingModule],
+ declarations: [ScrollToTopComponent],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ScrollToTopComponent);
+ component = fixture.componentInstance;
+ compDe = fixture.debugElement;
+
+ // Trigger initial data binding
+ fixture.detectChanges();
+
+ // Test data
+ expectedScrollThreshold = 300;
+ expectedArrowIcon = faArrowUp;
+
+ // Spies on component functions
+ // `.and.callThrough` will track the spy down the nested describes, see
+ // https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3Eand.callThrough%3C/code%3E
+ scrollToTopSpy = spyOn(component, 'scrollToTop').and.callThrough();
+ }));
+
+ afterAll(() => {
+ cleanStylesFromDOM();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('... should have `faArrowUp`', () => {
+ expectToEqual(component.faArrowUp, faArrowUp);
+ });
+
+ it('... should not have `isScrolled`', () => {
+ expect(component.isScrolled).toBeUndefined();
+ });
+
+ describe('#VIEW', () => {
+ describe('... should contain no button.awg-scroll-to-top if', () => {
+ it('... isScrolled is undefined', () => {
+ component.isScrolled = undefined;
+ detectChangesOnPush(fixture);
+
+ getAndExpectDebugElementByCss(compDe, 'button.awg-scroll-to-top', 0, 0);
+ });
+
+ it('... isScrolled is false', () => {
+ component.isScrolled = false;
+ detectChangesOnPush(fixture);
+
+ getAndExpectDebugElementByCss(compDe, 'button.awg-scroll-to-top', 0, 0);
+ });
+ });
+
+ describe('... with isScrolled set to true', () => {
+ beforeEach(() => {
+ component.isScrolled = true;
+ detectChangesOnPush(fixture);
+ });
+
+ it('... should contain one button.awg-scroll-to-top if isScrolled is true', () => {
+ getAndExpectDebugElementByCss(compDe, 'button.awg-scroll-to-top', 1, 1);
+ });
+
+ it('... should display arrow icon in scroll button ', () => {
+ const btnDes = getAndExpectDebugElementByCss(compDe, 'button.awg-scroll-to-top', 1, 1);
+ const faIconDes = getAndExpectDebugElementByCss(btnDes[0], 'fa-icon', 1, 1);
+ const faIconIns = faIconDes[0].componentInstance.icon;
+
+ expectToEqual(faIconIns, expectedArrowIcon);
+ });
+
+ it('... should trigger `scrollToTop` method on button click', fakeAsync(() => {
+ const btnDes = getAndExpectDebugElementByCss(compDe, 'button.awg-scroll-to-top', 1, 1);
+
+ // Trigger click with click helper & wait for changes
+ clickAndAwaitChanges(btnDes[0], fixture);
+
+ expectSpyCall(scrollToTopSpy, 1);
+ }));
+ });
+ });
+
+ describe('#Hostlistener checkScroll()', () => {
+ it('... should have a hostlistener `checkScroll`', () => {
+ expect(component.checkScroll).toBeDefined();
+ });
+
+ it('... should default to 0 if window.scrollY is undefined', () => {
+ const scrollEventBelowThreshold = new Event('scroll') as any;
+ Object.defineProperty(scrollEventBelowThreshold, 'currentTarget', {
+ value: { scrollY: undefined },
+ writable: true,
+ });
+ component.checkScroll(scrollEventBelowThreshold);
+
+ expectToBe(component.isScrolled, false);
+ });
+
+ it('... should set `isScrolled` to true if scrollY is above threshold', () => {
+ const scrollEventAboveThreshold = new Event('scroll') as any;
+ Object.defineProperty(scrollEventAboveThreshold, 'currentTarget', {
+ value: { scrollY: expectedScrollThreshold + 1 },
+ writable: true,
+ });
+ component.checkScroll(scrollEventAboveThreshold);
+
+ expectToBe(component.isScrolled, true);
+ });
+
+ it('... should set `isScrolled` to false if scrollY is below threshold', () => {
+ const scrollEventBelowThreshold = new Event('scroll') as any;
+ Object.defineProperty(scrollEventBelowThreshold, 'currentTarget', {
+ value: { scrollY: expectedScrollThreshold - 1 },
+ writable: true,
+ });
+ component.checkScroll(scrollEventBelowThreshold);
+
+ expectToBe(component.isScrolled, false);
+ });
+
+ it('... should toggle `isScrolled` based on scrollY position of scroll event', () => {
+ const scrollEventBelowThreshold = new Event('scroll') as any;
+ Object.defineProperty(scrollEventBelowThreshold, 'currentTarget', {
+ value: { scrollY: expectedScrollThreshold - 1 },
+ writable: true,
+ });
+ component.checkScroll(scrollEventBelowThreshold);
+
+ expectToBe(component.isScrolled, false);
+
+ const scrollEventAboveThreshold = new Event('scroll');
+ Object.defineProperty(scrollEventAboveThreshold, 'currentTarget', {
+ value: { scrollY: expectedScrollThreshold + 1 },
+ writable: true,
+ });
+ component.checkScroll(scrollEventAboveThreshold);
+
+ expectToBe(component.isScrolled, true);
+ });
+ });
+
+ describe('#scrollToTop()', () => {
+ it('... should have a method `scrollToTop`', () => {
+ expect(component.scrollToTop).toBeDefined();
+ });
+
+ it('... should trigger window:scrollTo with correct parameters', () => {
+ const scrollToSpy = spyOn(window, 'scrollTo');
+
+ component.scrollToTop();
+
+ expectSpyCall(scrollToSpy, 1, { top: 0, behavior: 'smooth' });
+ });
+
+ it('... should scroll to top of page', () => {
+ const scrollEventBelowThreshold = new Event('scroll') as any;
+ Object.defineProperty(scrollEventBelowThreshold, 'currentTarget', {
+ value: { scrollY: expectedScrollThreshold + 1 },
+ writable: true,
+ });
+ component.checkScroll(scrollEventBelowThreshold);
+
+ expectToBe(component.isScrolled, true);
+
+ component.scrollToTop();
+
+ expectToBe(window.scrollY, 0);
+ });
+ });
+});
diff --git a/src/app/shared/scroll-to-top/scroll-to-top.component.ts b/src/app/shared/scroll-to-top/scroll-to-top.component.ts
new file mode 100644
index 000000000..6fc26f755
--- /dev/null
+++ b/src/app/shared/scroll-to-top/scroll-to-top.component.ts
@@ -0,0 +1,56 @@
+import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core';
+
+import { faArrowUp } from '@fortawesome/free-solid-svg-icons';
+
+/**
+ * The ScrollToTop component.
+ *
+ * It contains the scroll-to-top button
+ * that is provided via the {@link SharedModule}.
+ */
+@Component({
+ selector: 'awg-scroll-to-top',
+ templateUrl: './scroll-to-top.component.html',
+ styleUrl: './scroll-to-top.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class ScrollToTopComponent {
+ /**
+ * Public variable: faArrowUp.
+ *
+ * It instantiates fontawesome's faArrowUp icon.
+ */
+ faArrowUp = faArrowUp;
+
+ /**
+ * Public variable: isScrolled.
+ *
+ * It keeps track of the visibility of the scroll-to-top button.
+ */
+ isScrolled: boolean;
+
+ /**
+ * HostListener: checkScroll.
+ *
+ * It checks the scroll position on the document and
+ * sets the visibility of the scroll-to-top button.
+ */
+ @HostListener('window:scroll', ['$event']) checkScroll(event: Event) {
+ const window = event.currentTarget as Window;
+ const scrollPosition = window.scrollY || 0;
+ const SCROLL_THRESHOLD = 300;
+
+ this.isScrolled = scrollPosition >= SCROLL_THRESHOLD;
+ }
+
+ /**
+ * Public method: scrollToTop.
+ *
+ * It scrolls to the top of the page.
+ *
+ * @returns {void} Scrolls to the top of the page.
+ */
+ scrollToTop(): void {
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ }
+}
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 9ea343ed7..3691fa79c 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -15,12 +15,14 @@ import { CompileHtmlModule } from './compile-html';
//
// Shared components
import { AddressComponent } from './address/address.component';
+import { ErrorAlertComponent } from './error-alert/error-alert.component';
import { HeadingComponent } from './heading/heading.component';
import { JsonViewerComponent } from './json-viewer/json-viewer.component';
import { LicenseComponent } from './license/license.component';
import { ModalComponent } from './modal/modal.component';
import { OpenStreetMapComponent } from './open-street-map/open-street-map.component';
import { RouterLinkButtonGroupComponent } from './router-link-button-group/router-link-button-group.component';
+import { ScrollToTopComponent } from './scroll-to-top/scroll-to-top.component';
import { TablePaginationComponent } from './table/table-pagination/table-pagination.component';
import { TableComponent } from './table/table.component';
import { ToastComponent } from './toast/toast.component';
@@ -55,12 +57,14 @@ import { OrderByPipe } from './order-by-pipe/order-by.pipe';
],
declarations: [
AddressComponent,
+ ErrorAlertComponent,
HeadingComponent,
JsonViewerComponent,
LicenseComponent,
ModalComponent,
OpenStreetMapComponent,
RouterLinkButtonGroupComponent,
+ ScrollToTopComponent,
TableComponent,
TablePaginationComponent,
ToastComponent,
@@ -82,12 +86,14 @@ import { OrderByPipe } from './order-by-pipe/order-by.pipe';
SharedNgbootstrapModule,
AddressComponent,
+ ErrorAlertComponent,
HeadingComponent,
JsonViewerComponent,
LicenseComponent,
ModalComponent,
OpenStreetMapComponent,
RouterLinkButtonGroupComponent,
+ ScrollToTopComponent,
TableComponent,
ToastComponent,
TwelveToneSpinnerComponent,
diff --git a/src/app/shared/table/table-pagination/table-pagination.component.spec.ts b/src/app/shared/table/table-pagination/table-pagination.component.spec.ts
index ce72fc3cb..56f765ae5 100644
--- a/src/app/shared/table/table-pagination/table-pagination.component.spec.ts
+++ b/src/app/shared/table/table-pagination/table-pagination.component.spec.ts
@@ -7,6 +7,8 @@ import { NgbConfig, NgbPagination, NgbPaginationModule } from '@ng-bootstrap/ng-
import {
expectSpyCall,
+ expectToBe,
+ expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -78,9 +80,7 @@ describe('TablePaginationComponent (DONE)', () => {
});
it('... should have FILTER_PAG_REGEX', () => {
- expect(component.FILTER_PAG_REGEX).toBeDefined();
-
- expect(component.FILTER_PAG_REGEX).withContext(`should equal /\\D/g`).toEqual(/\D/g);
+ expectToEqual(component.FILTER_PAG_REGEX, /\D/g);
});
it('... should not have called formatInput', () => {
@@ -118,15 +118,11 @@ describe('TablePaginationComponent (DONE)', () => {
});
it('... should have collectionSize', () => {
- expect(component.collectionSize).toBeDefined();
- expect(component.collectionSize)
- .withContext(`should equal ${expectedCollectionSize}`)
- .toEqual(expectedCollectionSize);
+ expectToBe(component.collectionSize, expectedCollectionSize);
});
it('... should have page', () => {
- expect(component.page).toBeDefined();
- expect(component.page).withContext(`should equal ${expectedPage}`).toEqual(expectedPage);
+ expectToBe(component.page, expectedPage);
});
describe('VIEW', () => {
@@ -201,8 +197,7 @@ describe('TablePaginationComponent (DONE)', () => {
const labelDe = getAndExpectDebugElementByCss(divDe[0], 'label#paginationInputLabel', 1, 1);
const labelEl = labelDe[0].nativeElement;
- expect(labelEl.textContent).toBeTruthy();
- expect(labelEl.textContent).withContext(`should be ${expectedLabel}`).toBe(expectedLabel);
+ expectToBe(labelEl.textContent, expectedLabel);
});
it('... should display recent page in input', () => {
@@ -217,8 +212,7 @@ describe('TablePaginationComponent (DONE)', () => {
);
const inputEl = inputDe[0].nativeElement;
- expect(inputEl.value).toBeTruthy();
- expect(inputEl.value).withContext(`should be ${expectedInputValue}`).toBe(expectedInputValue);
+ expectToBe(inputEl.value, expectedInputValue);
});
it('... should display `von pages.length` in span', () => {
@@ -230,8 +224,7 @@ describe('TablePaginationComponent (DONE)', () => {
const spanDe = getAndExpectDebugElementByCss(divDe[0], 'span#paginationDescription', 1, 1);
const spanEl = spanDe[0].nativeElement;
- expect(spanEl.textContent).toBeTruthy();
- expect(spanEl.textContent.trim()).withContext(`should be ${expectedSpanText}`).toBe(expectedSpanText);
+ expectToBe(spanEl.textContent.trim(), expectedSpanText);
});
});
@@ -257,7 +250,7 @@ describe('TablePaginationComponent (DONE)', () => {
input.value = '3';
component.replaceNonNumberInput(input);
- expect(input.value).toBe('3');
+ expectToBe(input.value, '3');
});
it('... by replacing non-numbers with empty string', () => {
@@ -265,7 +258,7 @@ describe('TablePaginationComponent (DONE)', () => {
input.value = 'Test';
component.replaceNonNumberInput(input);
- expect(input.value).toBe('');
+ expectToBe(input.value, '');
});
});
});
@@ -341,8 +334,7 @@ describe('TablePaginationComponent (DONE)', () => {
component.selectPage(expectedNewPage.toString());
- expect(component.page).toBeTruthy();
- expect(component.page).withContext(`should be ${expectedNewPage}`).toBe(expectedNewPage);
+ expectToBe(component.page, expectedNewPage);
});
it('... to 1 if the given value cannot be parsed to an integer', () => {
@@ -350,29 +342,25 @@ describe('TablePaginationComponent (DONE)', () => {
component.selectPage(expectedNewPage);
- expect(component.page).toBeTruthy();
- expect(component.page).withContext(`should be 1`).toBe(1);
+ expectToBe(component.page, 1);
const expectedNewPage2 = 'NaN';
component.selectPage(expectedNewPage2);
- expect(component.page).toBeTruthy();
- expect(component.page).withContext(`should be 1`).toBe(1);
+ expectToBe(component.page, 1);
const expectedNewPage3 = '_123';
component.selectPage(expectedNewPage3);
- expect(component.page).toBeTruthy();
- expect(component.page).withContext(`should be 1`).toBe(1);
+ expectToBe(component.page, 1);
});
it('... to 1 if the given value is undefined', () => {
component.selectPage(undefined);
- expect(component.page).toBeTruthy();
- expect(component.page).withContext(`should be 1`).toBe(1);
+ expectToBe(component.page, 1);
});
});
});
diff --git a/src/app/shared/table/table.component.spec.ts b/src/app/shared/table/table.component.spec.ts
index b2bd59f47..2241d9374 100644
--- a/src/app/shared/table/table.component.spec.ts
+++ b/src/app/shared/table/table.component.spec.ts
@@ -165,8 +165,8 @@ describe('TableComponent', () => {
});
it('... should have faSortUp and faSortDown icons', () => {
- expectToBe(component.faSortUp, faSortUp);
- expectToBe(component.faSortDown, faSortDown);
+ expectToEqual(component.faSortUp, faSortUp);
+ expectToEqual(component.faSortDown, faSortDown);
});
it('... should have tableOptions', () => {
@@ -244,14 +244,10 @@ describe('TableComponent', () => {
expectToEqual(component.tableData.filteredRows, expectedRowInputData);
expect(component.tableData.paginatedRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.paginatedRows$))
- .withContext(`should be resolved to ${expectedRowInputData}`)
- .toBeResolvedTo(expectedRowInputData);
+ expectAsync(lastValueFrom(component.tableData.paginatedRows$)).toBeResolvedTo(expectedRowInputData);
expect(component.tableData.totalRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.totalRows$))
- .withContext(`should be resolved to ${expectedRowInputData}`)
- .toBeResolvedTo(expectedRowInputData);
+ expectAsync(lastValueFrom(component.tableData.totalRows$)).toBeResolvedTo(expectedRowInputData);
}));
describe('... to empty object', () => {
@@ -268,14 +264,10 @@ describe('TableComponent', () => {
expectToEqual(component.tableData.filteredRows, []);
expect(component.tableData.paginatedRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.paginatedRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ expectAsync(lastValueFrom(component.tableData.paginatedRows$)).toBeResolvedTo([]);
expect(component.tableData.totalRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.totalRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ expectAsync(lastValueFrom(component.tableData.totalRows$)).toBeResolvedTo([]);
}));
it('... if rowInputData is not given', waitForAsync(() => {
@@ -291,14 +283,10 @@ describe('TableComponent', () => {
expectToEqual(component.tableData.filteredRows, []);
expect(component.tableData.paginatedRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.paginatedRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ expectAsync(lastValueFrom(component.tableData.paginatedRows$)).toBeResolvedTo([]);
expect(component.tableData.totalRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.totalRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ expectAsync(lastValueFrom(component.tableData.totalRows$)).toBeResolvedTo([]);
}));
it('... if both headerInputData and rowInputData are not given', waitForAsync(() => {
@@ -314,14 +302,10 @@ describe('TableComponent', () => {
expectToEqual(component.tableData.filteredRows, []);
expect(component.tableData.paginatedRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.paginatedRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ expectAsync(lastValueFrom(component.tableData.paginatedRows$)).toBeResolvedTo([]);
expect(component.tableData.totalRows$).toBeDefined();
- expectAsync(lastValueFrom(component.tableData.totalRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ expectAsync(lastValueFrom(component.tableData.totalRows$)).toBeResolvedTo([]);
}));
});
});
@@ -375,18 +359,14 @@ describe('TableComponent', () => {
// First call happens on ngOnInit()
expectSpyCall(onPageSizeChangeSpy, 2, expectedSearchFilter);
- expect(component.searchFilter).toBeDefined();
- expect(component.searchFilter)
- .withContext(`should equal ${expectedSearchFilter}`)
- .toBe(expectedSearchFilter);
+ expectToBe(component.searchFilter, expectedSearchFilter);
inputEl.value = otherSearchFilter;
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
expectSpyCall(onPageSizeChangeSpy, 3, otherSearchFilter);
- expect(component.searchFilter).toBeDefined();
- expect(component.searchFilter).withContext(`should equal ${otherSearchFilter}`).toBe(otherSearchFilter);
+ expectToBe(component.searchFilter, otherSearchFilter);
});
it('... should trigger on change of selectedPageSize in upper dropdown menu', fakeAsync(() => {
@@ -575,14 +555,10 @@ describe('TableComponent', () => {
expectToEqual(component.tableData.filteredRows, []);
expect(component.tableData.paginatedRows$).toBeDefined();
- await expectAsync(lastValueFrom(component.tableData.paginatedRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ await expectAsync(lastValueFrom(component.tableData.paginatedRows$)).toBeResolvedTo([]);
expect(component.tableData.totalRows$).toBeDefined();
- await expectAsync(lastValueFrom(component.tableData.totalRows$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ await expectAsync(lastValueFrom(component.tableData.totalRows$)).toBeResolvedTo([]);
});
});
@@ -596,9 +572,7 @@ describe('TableComponent', () => {
expect(component.tableData).toBeDefined();
expectAsync(lastValueFrom(component.tableData.paginatedRows$)).toBeResolved();
- expectAsync(lastValueFrom(component.tableData.paginatedRows$))
- .withContext(`should be resolved to ${expectedPaginatedRows}`)
- .toBeResolvedTo(expectedPaginatedRows);
+ expectAsync(lastValueFrom(component.tableData.paginatedRows$)).toBeResolvedTo(expectedPaginatedRows);
}));
describe('should not do anything', () => {
diff --git a/src/app/shared/toast/toast.component.spec.ts b/src/app/shared/toast/toast.component.spec.ts
index c50d50d0f..c44329d17 100644
--- a/src/app/shared/toast/toast.component.spec.ts
+++ b/src/app/shared/toast/toast.component.spec.ts
@@ -1,7 +1,7 @@
import { Component, DebugElement, EventEmitter, Input, Output, TemplateRef, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-import { getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import { expectToBe, expectToEqual, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { ToastComponent } from './toast.component';
import { Toast, ToastService } from './toast.service';
@@ -24,7 +24,7 @@ class NgbToastStubComponent {
@Input()
autohide: string;
@Input()
- delay: string;
+ delay: number;
@Output()
hide: EventEmitter = new EventEmitter();
}
@@ -81,8 +81,8 @@ describe('ToastComponent (DONE)', () => {
it('... should have added one toast to toast service', () => {
expect(toastService.toasts).toBeDefined();
- expect(toastService.toasts.length).withContext(`should be 1`).toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast}`).toEqual(expectedToast);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast);
});
describe('VIEW', () => {
@@ -94,38 +94,28 @@ describe('ToastComponent (DONE)', () => {
const toastDes = getAndExpectDebugElementByDirective(compDe, NgbToastStubComponent, 1, 1);
const toastCmp = toastDes[0].injector.get(NgbToastStubComponent) as NgbToastStubComponent;
- expect(toastCmp.header).toBeDefined();
- expect(toastCmp.header)
- .withContext(`should be ${expectedToast.options.header}`)
- .toBe(expectedToast.options.header);
+ expectToBe(toastCmp.header, expectedToast.options.header);
});
it('... should pass down classname to ngb-toast component (stubbed) if given', () => {
const toastDes = getAndExpectDebugElementByDirective(compDe, NgbToastStubComponent, 1, 1);
const toastCmp = toastDes[0].injector.get(NgbToastStubComponent) as NgbToastStubComponent;
- expect(toastCmp.class).toBeDefined();
- expect(toastCmp.class)
- .withContext(`should be ${expectedToast.options.classname}`)
- .toBe(expectedToast.options.classname);
+ expectToBe(toastCmp.class, expectedToast.options.classname);
});
it('... should pass down autohide=true to ngb-toast component (stubbed)', () => {
const toastDes = getAndExpectDebugElementByDirective(compDe, NgbToastStubComponent, 1, 1);
const toastCmp = toastDes[0].injector.get(NgbToastStubComponent) as NgbToastStubComponent;
- expect(toastCmp.autohide).toBeDefined();
- expect(toastCmp.autohide).toBeTrue();
+ expectToBe(toastCmp.autohide, true);
});
it('... should pass down delay to ngb-toast component (stubbed)', () => {
const toastDes = getAndExpectDebugElementByDirective(compDe, NgbToastStubComponent, 1, 1);
const toastCmp = toastDes[0].injector.get(NgbToastStubComponent) as NgbToastStubComponent;
- expect(toastCmp.delay).toBeDefined();
- expect(toastCmp.delay)
- .withContext(`should be ${expectedToast.options.delay}`)
- .toBe(expectedToast.options.delay);
+ expectToBe(toastCmp.delay, expectedToast.options.delay);
});
it('... should pass down default delay (=5000) to ngb-toast component (stubbed) if no delay is given', () => {
@@ -139,8 +129,7 @@ describe('ToastComponent (DONE)', () => {
const toastDes = getAndExpectDebugElementByDirective(compDe, NgbToastStubComponent, 1, 1);
const toastCmp = toastDes[0].injector.get(NgbToastStubComponent) as NgbToastStubComponent;
- expect(toastCmp.delay).toBeDefined();
- expect(toastCmp.delay).withContext(`should be 5000`).toBe(5000);
+ expectToBe(toastCmp.delay, 5000);
});
it('... should remove toast from service on hide', () => {
@@ -149,8 +138,7 @@ describe('ToastComponent (DONE)', () => {
toastCmp.hide.emit();
- expect(toastService.toasts).toBeDefined();
- expect(toastService.toasts.length).withContext(`should be 0`).toBe(0);
+ expectToBe(toastService.toasts.length, 0);
});
});
@@ -162,7 +150,7 @@ describe('ToastComponent (DONE)', () => {
it('... should return false if given toast is not a template, but string', () => {
const check = component.isTemplate(expectedToast);
- expect(check).toBeFalse();
+ expectToBe(check, false);
});
it('... should return true if given toast is a template', () => {
@@ -173,7 +161,7 @@ describe('ToastComponent (DONE)', () => {
const check = component.isTemplate(expectedTplToast);
- expect(check).toBeTrue();
+ expectToBe(check, true);
});
});
});
diff --git a/src/app/shared/toast/toast.service.spec.ts b/src/app/shared/toast/toast.service.spec.ts
index 7ec7fdca6..4500aafe3 100644
--- a/src/app/shared/toast/toast.service.spec.ts
+++ b/src/app/shared/toast/toast.service.spec.ts
@@ -1,6 +1,8 @@
import { Component, TemplateRef, ViewChild } from '@angular/core';
import { TestBed } from '@angular/core/testing';
+import { expectToBe, expectToEqual } from '@testing/expect-helper';
+
import { Toast, ToastService } from './toast.service';
// Mock component to get templateRef
@@ -45,8 +47,7 @@ describe('ToastService (DONE)', () => {
});
it('... should have empty toast array', () => {
- expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts).withContext('should equal empty array []').toEqual([]);
+ expectToEqual(toastService.toasts, []);
});
describe('#add()', () => {
@@ -59,8 +60,8 @@ describe('ToastService (DONE)', () => {
toastService.add(expectedToast1);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have one entry').toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast1}`).toEqual(expectedToast1);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast1);
});
it('... should add given template to toast array', () => {
@@ -74,8 +75,8 @@ describe('ToastService (DONE)', () => {
toastService.add(expectedTplToast);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have one entry').toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedTplToast}`).toEqual(expectedTplToast);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedTplToast);
});
it('... should only add textOrTpl if options not given', () => {
@@ -83,8 +84,8 @@ describe('ToastService (DONE)', () => {
toastService.add(expectedToast1);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have one entry').toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast1}`).toEqual(expectedToast1);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast1);
});
it('... should add options if given with text message', () => {
@@ -92,8 +93,8 @@ describe('ToastService (DONE)', () => {
toastService.add(expectedToast2);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have one entry').toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast2}`).toEqual(expectedToast2);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast2);
});
it('... should add options if given with template message', () => {
@@ -107,8 +108,8 @@ describe('ToastService (DONE)', () => {
toastService.add(expectedTplToast);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have one entry').toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedTplToast}`).toEqual(expectedTplToast);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedTplToast);
});
});
@@ -129,9 +130,9 @@ describe('ToastService (DONE)', () => {
toastService.remove(expectedOtherToast);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have two entries').toBe(2);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast1}`).toEqual(expectedToast1);
- expect(toastService.toasts[1]).withContext(`should equal ${expectedToast2}`).toEqual(expectedToast2);
+ expectToBe(toastService.toasts.length, 2);
+ expectToEqual(toastService.toasts[0], expectedToast1);
+ expectToEqual(toastService.toasts[1], expectedToast2);
});
it('... should do nothing if options do not match', () => {
@@ -140,9 +141,9 @@ describe('ToastService (DONE)', () => {
toastService.remove(otherOptionsToast);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have two entries').toBe(2);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast1}`).toEqual(expectedToast1);
- expect(toastService.toasts[1]).withContext(`should equal ${expectedToast2}`).toEqual(expectedToast2);
+ expectToBe(toastService.toasts.length, 2);
+ expectToEqual(toastService.toasts[0], expectedToast1);
+ expectToEqual(toastService.toasts[1], expectedToast2);
});
it('... should remove existing toast from toast array (without options)', () => {
@@ -150,11 +151,8 @@ describe('ToastService (DONE)', () => {
toastService.remove(expectedToast1);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have one entry').toBe(1);
- expect(toastService.toasts[0])
- .withContext(`should not equal ${expectedToast1}`)
- .not.toEqual(expectedToast1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast2}`).toEqual(expectedToast2);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast2);
});
it('... should remove existing toast from toast array (with options)', () => {
@@ -162,11 +160,8 @@ describe('ToastService (DONE)', () => {
toastService.remove(expectedToast2);
expect(toastService.toasts).toBeTruthy();
- expect(toastService.toasts.length).withContext('should have one entry').toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast1}`).toEqual(expectedToast1);
- expect(toastService.toasts[1])
- .withContext(`should not equal ${expectedToast2}`)
- .not.toEqual(expectedToast2);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast1);
});
});
});
diff --git a/src/app/shared/view-handle-button-group/view-handle-button-group.component.spec.ts b/src/app/shared/view-handle-button-group/view-handle-button-group.component.spec.ts
index e05d11ca8..5f537de0f 100644
--- a/src/app/shared/view-handle-button-group/view-handle-button-group.component.spec.ts
+++ b/src/app/shared/view-handle-button-group/view-handle-button-group.component.spec.ts
@@ -7,11 +7,12 @@ import { faDiagramProject, faGripHorizontal, faTable } from '@fortawesome/free-s
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
import Spy = jasmine.Spy;
-import { expectSpyCall, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, getAndExpectDebugElementByCss } from '@testing/expect-helper';
-import { ViewHandleButtonGroupComponent } from './view-handle-button-group.component';
import { ViewHandle, ViewHandleTypes } from './view-handle.model';
+import { ViewHandleButtonGroupComponent } from './view-handle-button-group.component';
+
describe('ViewHandleButtonGroupComponent (DONE)', () => {
let component: ViewHandleButtonGroupComponent;
let fixture: ComponentFixture;
@@ -178,8 +179,8 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
});
it('... should create the viewHandleControlForm with correct viewHandleControl value', () => {
- expect(component.viewHandleControlForm.controls['viewHandleControl'].value).toBeTruthy();
- expect(component.viewHandleControlForm.controls['viewHandleControl'].value).toBe(
+ expectToBe(
+ component.viewHandleControlForm.controls['viewHandleControl'].value,
expectedSelectedViewType
);
});
@@ -188,8 +189,7 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
expect(component.viewHandleControl).toBeDefined();
expect(component.viewHandleControl).toBeInstanceOf(UntypedFormControl);
- expect(component.viewHandleControl.value).toBeTruthy();
- expect(component.viewHandleControl.value).toBe(expectedSelectedViewType);
+ expectToBe(component.viewHandleControl.value, expectedSelectedViewType);
});
it('... should trigger the `listenToUserInputChange()` method', () => {
@@ -355,8 +355,8 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
});
it('... should return the type of a given view handle', () => {
- expect(component.viewHandleTracker(0, expectedViewHandles[0])).toBe(ViewHandleTypes.GRAPH);
- expect(component.viewHandleTracker(1, expectedViewHandles[1])).toBe(ViewHandleTypes.TABLE);
+ expectToBe(component.viewHandleTracker(0, expectedViewHandles[0]), ViewHandleTypes.GRAPH);
+ expectToBe(component.viewHandleTracker(1, expectedViewHandles[1]), ViewHandleTypes.TABLE);
});
});
@@ -377,7 +377,7 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
);
for (let i = 0; i < expectedViewHandles.length; i++) {
- expect(inputDes[i].nativeElement.type).toBe('radio');
+ expectToBe(inputDes[i].nativeElement.type, 'radio');
}
});
@@ -396,10 +396,7 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
);
for (let i = 0; i < expectedViewHandles.length; i++) {
- expect(inputDes[i].attributes['ng-reflect-value']).toBeTruthy();
- expect(inputDes[i].attributes['ng-reflect-value'])
- .withContext(`should be ${expectedViewHandles[i].type}`)
- .toBe(expectedViewHandles[i].type);
+ expectToBe(inputDes[i].attributes['ng-reflect-value'], expectedViewHandles[i].type);
}
});
@@ -421,20 +418,9 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
const inputEl2 = inputDes[1].nativeElement;
const inputEl3 = inputDes[2].nativeElement;
- expect(inputEl1.id).toBeTruthy();
- expect(inputEl1.id)
- .withContext(`should be '${expectedViewHandles}-view-button'`)
- .toBe(`${expectedViewHandles[0].type}-view-button`);
-
- expect(inputEl2.id).toBeTruthy();
- expect(inputEl2.id)
- .withContext(`should be '${expectedViewHandles}-view-button'`)
- .toBe(`${expectedViewHandles[1].type}-view-button`);
-
- expect(inputEl3.id).toBeTruthy();
- expect(inputEl3.id)
- .withContext(`should be '${expectedViewHandles}-view-button'`)
- .toBe(`${expectedViewHandles[2].type}-view-button`);
+ expectToBe(inputEl1.id, `${expectedViewHandles[0].type}-view-button`);
+ expectToBe(inputEl2.id, `${expectedViewHandles[1].type}-view-button`);
+ expectToBe(inputEl3.id, `${expectedViewHandles[2].type}-view-button`);
});
it('... should have as many label elements in div.btn-group as viewHandles given', () => {
@@ -491,10 +477,7 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
);
for (let i = 0; i < expectedViewHandles.length; i++) {
- expect(labelDes[i].attributes['for']).toBeTruthy();
- expect(labelDes[i].attributes['for'])
- .withContext(`should be ${expectedViewHandles[i].type}-view-button`)
- .toBe(`${expectedViewHandles[i].type}-view-button`);
+ expectToBe(labelDes[i].attributes['for'], `${expectedViewHandles[i].type}-view-button`);
}
});
@@ -513,10 +496,7 @@ describe('ViewHandleButtonGroupComponent (DONE)', () => {
);
for (let i = 0; i < expectedViewHandles.length; i++) {
- expect(labelDes[i].attributes['ng-reflect-ngb-tooltip']).toBeTruthy();
- expect(labelDes[i].attributes['ng-reflect-ngb-tooltip'])
- .withContext(`should be '${expectedViewHandles[i].type} view'`)
- .toBe(expectedViewHandles[i].type + ' view');
+ expectToBe(labelDes[i].attributes['ng-reflect-ngb-tooltip'], expectedViewHandles[i].type + ' view');
}
});
});
diff --git a/src/app/side-info/contact-info/contact-info.component.spec.ts b/src/app/side-info/contact-info/contact-info.component.spec.ts
index 1e3fa9e56..d23acc937 100644
--- a/src/app/side-info/contact-info/contact-info.component.spec.ts
+++ b/src/app/side-info/contact-info/contact-info.component.spec.ts
@@ -7,6 +7,8 @@ import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import {
expectSpyCall,
+ expectToBe,
+ expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -14,8 +16,8 @@ import {
import { AppConfig } from '@awg-app/app.config';
import { METADATA } from '@awg-core/core-data';
import { MetaContact, MetaPage, MetaSectionTypes } from '@awg-core/core-models';
-
import { CoreService } from '@awg-core/services';
+
import { ContactInfoComponent } from './contact-info.component';
// Mock address component
@@ -103,13 +105,12 @@ describe('ContactInfoComponent (DONE)', () => {
it('... injected service should use provided mockValue', () => {
const coreService = TestBed.inject(CoreService);
- expect(mockCoreService === coreService).toBe(true);
+ expectToBe(mockCoreService === coreService, true);
});
describe('BEFORE initial data binding', () => {
it('... should have contact info header', () => {
- expect(component.contactInfoHeader).toBeDefined();
- expect(component.contactInfoHeader).toBe(expectedContactInfoHeader);
+ expectToBe(component.contactInfoHeader, expectedContactInfoHeader);
});
it('... should not have metadata nor open street map links', () => {
@@ -153,8 +154,7 @@ describe('ContactInfoComponent (DONE)', () => {
const headerDes = getAndExpectDebugElementByCss(compDe, 'h5#awg-contact-info-header', 1, 1);
const headerEl = headerDes[0].nativeElement;
- expect(headerEl).toBeDefined();
- expect(headerEl.textContent).toBeFalsy();
+ expectToBe(headerEl.textContent, '');
});
it('... should contain one address component (stubbed)', () => {
@@ -204,17 +204,11 @@ describe('ContactInfoComponent (DONE)', () => {
});
it('... should return pageMetaData', () => {
- expect(component.pageMetaData).toBeDefined();
- expect(component.pageMetaData)
- .withContext(`should be ${expectedPageMetaData}`)
- .toBe(expectedPageMetaData);
+ expectToEqual(component.pageMetaData, expectedPageMetaData);
});
it('... should return contactMetaData', () => {
- expect(component.contactMetaData).toBeDefined();
- expect(component.contactMetaData)
- .withContext(`should be ${expectedContactMetaData}`)
- .toBe(expectedContactMetaData);
+ expectToEqual(component.contactMetaData, expectedContactMetaData);
});
});
@@ -224,17 +218,11 @@ describe('ContactInfoComponent (DONE)', () => {
});
it('... should return osmEmbedUrl', () => {
- expect(component.osmEmbedUrl).toBeDefined();
- expect(component.osmEmbedUrl)
- .withContext(`should equal ${expectedOsmEmbedUrl}`)
- .toEqual(expectedOsmEmbedUrl);
+ expectToEqual(component.osmEmbedUrl, expectedOsmEmbedUrl);
});
it('... should return osmLinkUrl', () => {
- expect(component.osmLinkUrl).toBeDefined();
- expect(component.osmLinkUrl)
- .withContext(`should equal ${expectedOsmLinkUrl}`)
- .toEqual(expectedOsmLinkUrl);
+ expectToEqual(component.osmLinkUrl, expectedOsmLinkUrl);
});
});
@@ -243,38 +231,23 @@ describe('ContactInfoComponent (DONE)', () => {
const headerDes = getAndExpectDebugElementByCss(compDe, 'h5#awg-contact-info-header', 1, 1);
const headerEl = headerDes[0].nativeElement;
- expect(headerEl).toBeDefined();
- expect(headerEl.textContent)
- .withContext(`should be ${expectedContactInfoHeader}`)
- .toBe(expectedContactInfoHeader);
+ expectToBe(headerEl.textContent, expectedContactInfoHeader);
});
it('... should pass down `pageMetaData` and `contactMetaData` to address component', () => {
const addressDes = getAndExpectDebugElementByDirective(compDe, AddressStubComponent, 1, 1);
const addressCmp = addressDes[0].injector.get(AddressStubComponent) as AddressStubComponent;
- expect(addressCmp.pageMetaData).toBeTruthy();
- expect(addressCmp.pageMetaData)
- .withContext(`should be ${expectedPageMetaData}`)
- .toBe(expectedPageMetaData);
-
- expect(addressCmp.contactMetaData).toBeTruthy();
- expect(addressCmp.contactMetaData)
- .withContext(`should be ${expectedContactMetaData}`)
- .toBe(expectedContactMetaData);
+ expectToEqual(addressCmp.pageMetaData, expectedPageMetaData);
+ expectToEqual(addressCmp.contactMetaData, expectedContactMetaData);
});
it('... should pass down `osmEmbedUrl` and `osmLinkUrl` to OpenStreetMap component', () => {
const osmDes = getAndExpectDebugElementByDirective(compDe, OpenStreetMapStubComponent, 1, 1);
const osmCmp = osmDes[0].injector.get(OpenStreetMapStubComponent) as OpenStreetMapStubComponent;
- expect(osmCmp.osmEmbedUrl).toBeTruthy();
- expect(osmCmp.osmEmbedUrl)
- .withContext(`should equal ${expectedOsmEmbedUrl}`)
- .toEqual(expectedOsmEmbedUrl);
-
- expect(osmCmp.osmLinkUrl).toBeTruthy();
- expect(osmCmp.osmLinkUrl).withContext(`should equal ${expectedOsmLinkUrl}`).toEqual(expectedOsmLinkUrl);
+ expectToEqual(osmCmp.osmEmbedUrl, expectedOsmEmbedUrl);
+ expectToEqual(osmCmp.osmLinkUrl, expectedOsmLinkUrl);
});
});
});
diff --git a/src/app/side-info/edition-info/edition-info.component.html b/src/app/side-info/edition-info/edition-info.component.html
index d23206914..dd4650c25 100644
--- a/src/app/side-info/edition-info/edition-info.component.html
+++ b/src/app/side-info/edition-info/edition-info.component.html
@@ -31,6 +31,16 @@
>{{ editionRouteConstants.ROWTABLES.full }}
+
+
+
diff --git a/src/app/side-info/edition-info/edition-info.component.spec.ts b/src/app/side-info/edition-info/edition-info.component.spec.ts
index c34f0f0ed..59b133070 100644
--- a/src/app/side-info/edition-info/edition-info.component.spec.ts
+++ b/src/app/side-info/edition-info/edition-info.component.spec.ts
@@ -16,9 +16,9 @@ import {
} from '@testing/expect-helper';
import { RouterLinkStubDirective } from 'testing/router-stubs';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS, EDITION_TYPE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import { EditionComplex } from '@awg-views/edition-view/models';
+import { EditionComplexesService } from '@awg-views/edition-view/services';
import { EditionInfoComponent } from './edition-info.component';
@@ -26,30 +26,32 @@ import { EditionInfoComponent } from './edition-info.component';
function generateExpectedOrderOfRouterlinks(editionComplexes: EditionComplex[]): string[][] {
const editionOverviewLink = [[EDITION_ROUTE_CONSTANTS.EDITION.route, EDITION_ROUTE_CONSTANTS.SERIES.route]];
const rowTablesLink = [[EDITION_ROUTE_CONSTANTS.EDITION.route, EDITION_ROUTE_CONSTANTS.ROWTABLES.route]];
+ const prefaceLink = [[EDITION_ROUTE_CONSTANTS.EDITION.route, EDITION_ROUTE_CONSTANTS.PREFACE.route]];
const editionLinks = editionComplexes.flatMap(complex => {
const routes = [[complex.baseRoute, EDITION_ROUTE_CONSTANTS.EDITION_SHEETS.route]];
- if (complex === EDITION_COMPLEXES.OP25) {
+ if (complex === EditionComplexesService.getEditionComplexById('OP25')) {
routes.push([complex.baseRoute, EDITION_ROUTE_CONSTANTS.EDITION_GRAPH.route]);
}
return routes;
});
- return [...editionOverviewLink, ...rowTablesLink, ...editionLinks];
+ return [...editionOverviewLink, ...rowTablesLink, ...prefaceLink, ...editionLinks];
}
function generateExpectedOrderOfHeaders(editionComplexes: EditionComplex[]): string[] {
const editionOverviewHeader = EDITION_ROUTE_CONSTANTS.SERIES.full;
const rowTablesHeader = EDITION_ROUTE_CONSTANTS.ROWTABLES.full;
+ const prefaceHeader = EDITION_ROUTE_CONSTANTS.PREFACE.full;
const editionHeaders = editionComplexes.flatMap(complex => {
- if (complex === EDITION_COMPLEXES.OP25) {
+ if (complex === EditionComplexesService.getEditionComplexById('OP25')) {
return [EDITION_TYPE_CONSTANTS.SKETCH_EDITION.full, EDITION_ROUTE_CONSTANTS.EDITION_GRAPH.full];
}
return [EDITION_TYPE_CONSTANTS.SKETCH_EDITION.full];
});
- return [editionOverviewHeader, rowTablesHeader, ...editionHeaders];
+ return [editionOverviewHeader, rowTablesHeader, prefaceHeader, ...editionHeaders];
}
describe('EditionInfoComponent (DONE)', () => {
@@ -93,17 +95,17 @@ describe('EditionInfoComponent (DONE)', () => {
// Test data
expectedEditionComplexes = [
- EDITION_COMPLEXES.OP3,
- EDITION_COMPLEXES.OP4,
- EDITION_COMPLEXES.OP12,
- EDITION_COMPLEXES.OP23,
- EDITION_COMPLEXES.OP25,
- EDITION_COMPLEXES.M22,
- EDITION_COMPLEXES.M30,
- EDITION_COMPLEXES.M31,
- EDITION_COMPLEXES.M34,
- EDITION_COMPLEXES.M35_42,
- EDITION_COMPLEXES.M37,
+ EditionComplexesService.getEditionComplexById('OP3'),
+ EditionComplexesService.getEditionComplexById('OP4'),
+ EditionComplexesService.getEditionComplexById('OP12'),
+ EditionComplexesService.getEditionComplexById('OP23'),
+ EditionComplexesService.getEditionComplexById('OP25'),
+ EditionComplexesService.getEditionComplexById('M22'),
+ EditionComplexesService.getEditionComplexById('M30'),
+ EditionComplexesService.getEditionComplexById('M31'),
+ EditionComplexesService.getEditionComplexById('M34'),
+ EditionComplexesService.getEditionComplexById('M35_42'),
+ EditionComplexesService.getEditionComplexById('M37'),
];
expectedOrderOfRouterlinks = generateExpectedOrderOfRouterlinks(expectedEditionComplexes);
expectedOrderOfHeaders = generateExpectedOrderOfHeaders(expectedEditionComplexes);
@@ -207,7 +209,7 @@ describe('EditionInfoComponent (DONE)', () => {
});
});
- it('... should display item header buttons with rowtables and edition series', () => {
+ it('... should display item header buttons', () => {
// Header debug elements
const itemHeaderDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-header', 3, 3);
@@ -265,7 +267,7 @@ describe('EditionInfoComponent (DONE)', () => {
expectToContain(itemBodyEl.classList, 'show');
});
- it('... should contain item body with 5 paragraphs in first item', () => {
+ it('... should contain item body with 3 paragraphs in first item', () => {
// Div.accordion-item
const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', 3, 3);
@@ -273,7 +275,7 @@ describe('EditionInfoComponent (DONE)', () => {
const itemBodyDes = getAndExpectDebugElementByCss(itemDes[0], 'div.accordion-body', 1, 1);
// Paragraph
- getAndExpectDebugElementByCss(itemBodyDes[0], 'p', 2, 2);
+ getAndExpectDebugElementByCss(itemBodyDes[0], 'p', 3, 3);
});
it('... should contain item body with 5 paragraphs in second item', () => {
@@ -364,7 +366,7 @@ describe('EditionInfoComponent (DONE)', () => {
const linkDe = linkDes[index];
const expectedRouterLink = expectedOrderOfRouterlinks[index];
- expect(routerLink.navigatedTo).toBeNull();
+ expectToBe(routerLink.navigatedTo, null);
click(linkDe);
fixture.detectChanges();
diff --git a/src/app/side-info/edition-info/edition-info.component.ts b/src/app/side-info/edition-info/edition-info.component.ts
index 033ca2ddf..5330e3936 100644
--- a/src/app/side-info/edition-info/edition-info.component.ts
+++ b/src/app/side-info/edition-info/edition-info.component.ts
@@ -1,8 +1,8 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS, EDITION_TYPE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import { EditionComplex } from '@awg-views/edition-view/models';
+import { EditionComplexesService } from '@awg-views/edition-view/services';
/**
* The EditionInfo component.
@@ -29,17 +29,17 @@ export class EditionInfoComponent {
* It keeps the array of displayed edition complexes.
*/
readonly DISPLAYED_EDITION_COMPLEXES: EditionComplex[] = [
- EDITION_COMPLEXES.OP3,
- EDITION_COMPLEXES.OP4,
- EDITION_COMPLEXES.OP12,
- EDITION_COMPLEXES.OP23,
- EDITION_COMPLEXES.OP25,
- EDITION_COMPLEXES.M22,
- EDITION_COMPLEXES.M30,
- EDITION_COMPLEXES.M31,
- EDITION_COMPLEXES.M34,
- EDITION_COMPLEXES.M35_42,
- EDITION_COMPLEXES.M37,
+ EditionComplexesService.getEditionComplexById('OP3'),
+ EditionComplexesService.getEditionComplexById('OP4'),
+ EditionComplexesService.getEditionComplexById('OP12'),
+ EditionComplexesService.getEditionComplexById('OP23'),
+ EditionComplexesService.getEditionComplexById('OP25'),
+ EditionComplexesService.getEditionComplexById('M22'),
+ EditionComplexesService.getEditionComplexById('M30'),
+ EditionComplexesService.getEditionComplexById('M31'),
+ EditionComplexesService.getEditionComplexById('M34'),
+ EditionComplexesService.getEditionComplexById('M35_42'),
+ EditionComplexesService.getEditionComplexById('M37'),
];
/**
diff --git a/src/app/side-info/resource-info/resource-info.component.spec.ts b/src/app/side-info/resource-info/resource-info.component.spec.ts
index 92c3a7dda..d0dddcb1f 100644
--- a/src/app/side-info/resource-info/resource-info.component.spec.ts
+++ b/src/app/side-info/resource-info/resource-info.component.spec.ts
@@ -1,6 +1,6 @@
import { JsonPipe } from '@angular/common';
import { Component, DebugElement } from '@angular/core';
-import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
+import { ComponentFixture, TestBed, fakeAsync, waitForAsync } from '@angular/core/testing';
import { AbstractControl, ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
@@ -12,7 +12,7 @@ import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { clickAndAwaitChanges } from '@testing/click-helper';
-import { expectSpyCall, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { mockSearchResponseJson } from '@testing/mock-data';
import { mockConsole } from '@testing/mock-helper';
@@ -131,7 +131,7 @@ describe('ResourceInfoComponent (DONE)', () => {
});
it('... injected service should use provided mockValue', () => {
- expect(dataStreamerService === mockDataStreamerService).toBe(true);
+ expectToBe(dataStreamerService === mockDataStreamerService, true);
});
describe('BEFORE initial data binding', () => {
@@ -152,15 +152,14 @@ describe('ResourceInfoComponent (DONE)', () => {
});
it('... should have empty resourceInfoData', () => {
- expect(component.resourceInfoData).withContext('should be defined').toBeDefined();
- expect(component.resourceInfoData).withContext('should equal new ResourceInfo').toEqual(new ResourceInfo());
+ expectToEqual(component.resourceInfoData, new ResourceInfo());
});
it('... should have fa-icons', () => {
- expect(component.faArrowLeft).withContext('should be faArrowLeft').toBe(faArrowLeft);
- expect(component.faChevronLeft).withContext('should be faChevronLeft').toBe(faChevronLeft);
- expect(component.faChevronRight).withContext('should be faChevronRight').toBe(faChevronRight);
- expect(component.faTimesCircle).withContext('should be faTimesCircle').toBe(faTimesCircle);
+ expectToEqual(component.faArrowLeft, faArrowLeft);
+ expectToEqual(component.faChevronLeft, faChevronLeft);
+ expectToEqual(component.faChevronRight, faChevronRight);
+ expectToEqual(component.faTimesCircle, faTimesCircle);
});
describe('VIEW', () => {
@@ -254,8 +253,7 @@ describe('ResourceInfoComponent (DONE)', () => {
it('... should have got `resourceId` from dataStreamerService', () => {
expectSpyCall(dataStreamerResourceIdSpy, 1);
- expect(component.resourceId).withContext('should be truthy').toBeTruthy();
- expect(component.resourceId).withContext(`should be ${expectedResourceId}`).toBe(expectedResourceId);
+ expectToBe(component.resourceId, expectedResourceId);
});
it('... should have got searchResponseWithQuery from dataStreamerService', () => {
@@ -268,11 +266,8 @@ describe('ResourceInfoComponent (DONE)', () => {
expectSpyCall(updateResourceInfoSpy, 1, [expectedResourceId, expectedResponseClone]);
});
it('... should have set `goToIndex` and `resultSize` (via _updateResourceInfo)', () => {
- expect(component.resultSize).withContext('should be truthy').toBeTruthy();
- expect(component.resultSize).withContext(`should be ${expectedResultSize}`).toBe(expectedResultSize);
-
- expect(component.goToIndex).withContext('should be truthy').toBeTruthy();
- expect(component.goToIndex).withContext(`should be ${expectedGoToIndex}`).toBe(expectedGoToIndex);
+ expectToBe(component.resultSize, expectedResultSize);
+ expectToBe(component.goToIndex, expectedGoToIndex);
});
it('... should have called _buildForm with `goToIndex` and `resultSize`', () => {
@@ -318,7 +313,7 @@ describe('ResourceInfoComponent (DONE)', () => {
// Check console
expectSpyCall(consoleSpy, 1, expectedLogMessage);
- expect(mockConsole.get(0)).withContext(`should be ${expectedLogMessage}`).toEqual(expectedLogMessage);
+ expectToEqual(mockConsole.get(0), expectedLogMessage);
});
});
@@ -330,11 +325,8 @@ describe('ResourceInfoComponent (DONE)', () => {
});
it('... should set `goToIndex` and `resultSize`', () => {
- expect(component.resultSize).withContext('should be truthy').toBeTruthy();
- expect(component.resultSize).withContext(`should be ${expectedResultSize}`).toBe(expectedResultSize);
-
- expect(component.goToIndex).withContext('should be truthy').toBeTruthy();
- expect(component.goToIndex).withContext(`should be ${expectedGoToIndex}`).toBe(expectedGoToIndex);
+ expectToBe(component.resultSize, expectedResultSize);
+ expectToBe(component.goToIndex, expectedGoToIndex);
});
it('... should change `goToIndex` and `resultSize` depending on input', () => {
@@ -346,11 +338,8 @@ describe('ResourceInfoComponent (DONE)', () => {
(component as any)._updateResourceInfo(expectedResourceId, otherResponseClone);
- expect(component.resultSize).withContext('should be truthy').toBeTruthy();
- expect(component.resultSize).withContext(`should be ${expectedResultSize}`).toBe(expectedResultSize);
-
- expect(component.goToIndex).withContext('should be truthy').toBeTruthy();
- expect(component.goToIndex).withContext(`should be ${expectedGoToIndex}`).toBe(expectedGoToIndex);
+ expectToBe(component.resultSize, expectedResultSize);
+ expectToBe(component.goToIndex, expectedGoToIndex);
});
describe('... should set `resourceInfoData` if', () => {
@@ -371,10 +360,7 @@ describe('ResourceInfoComponent (DONE)', () => {
},
};
- expect(component.resourceInfoData).withContext('should be truthy').toBeTruthy();
- expect(component.resourceInfoData)
- .withContext(`should be ${expectedResourceInfoData}`)
- .toEqual(expectedResourceInfoData);
+ expectToEqual(component.resourceInfoData, expectedResourceInfoData);
});
it('... only current and next resource given', () => {
@@ -398,13 +384,9 @@ describe('ResourceInfoComponent (DONE)', () => {
(component as any)._updateResourceInfo(expectedResourceId, otherResponseClone);
- expect(component.goToIndex).withContext('should be 1').toBe(1);
- expect(component.resultSize).withContext('should be 3').toBe(3);
-
- expect(component.resourceInfoData).withContext('should be truthy').toBeTruthy();
- expect(component.resourceInfoData)
- .withContext(`should be ${expectedResourceInfoData}`)
- .toEqual(expectedResourceInfoData);
+ expectToBe(component.goToIndex, 1);
+ expectToBe(component.resultSize, 3);
+ expectToEqual(component.resourceInfoData, expectedResourceInfoData);
});
it('... only current and previous resource given', () => {
@@ -428,15 +410,9 @@ describe('ResourceInfoComponent (DONE)', () => {
(component as any)._updateResourceInfo(expectedResourceId, otherResponseClone);
- expect(component.goToIndex).withContext(`should be ${expectedGoToIndex}`).toBe(expectedGoToIndex);
- expect(component.resultSize)
- .withContext(`should be ${expectedResultSize}`)
- .toBe(expectedResultSize);
-
- expect(component.resourceInfoData).withContext('should be truthy').toBeTruthy();
- expect(component.resourceInfoData)
- .withContext(`should be ${expectedResourceInfoData}`)
- .toEqual(expectedResourceInfoData);
+ expectToBe(component.goToIndex, expectedGoToIndex);
+ expectToBe(component.resultSize, expectedResultSize);
+ expectToEqual(component.resourceInfoData, expectedResourceInfoData);
});
it('... only current resource given', () => {
@@ -459,15 +435,9 @@ describe('ResourceInfoComponent (DONE)', () => {
(component as any)._updateResourceInfo(expectedResourceId, otherResponseClone);
- expect(component.goToIndex).withContext(`should be ${expectedGoToIndex}`).toBe(expectedGoToIndex);
- expect(component.resultSize)
- .withContext(`should be ${expectedResultSize}`)
- .toBe(expectedResultSize);
-
- expect(component.resourceInfoData).withContext('should be truthy').toBeTruthy();
- expect(component.resourceInfoData)
- .withContext(`should be ${expectedResourceInfoData}`)
- .toEqual(expectedResourceInfoData);
+ expectToBe(component.goToIndex, expectedGoToIndex);
+ expectToBe(component.resultSize, expectedResultSize);
+ expectToEqual(component.resourceInfoData, expectedResourceInfoData);
});
it('... no previous and current resource given', () => {
@@ -500,15 +470,9 @@ describe('ResourceInfoComponent (DONE)', () => {
(component as any)._updateResourceInfo(expectedResourceId, otherResponseClone);
- expect(component.goToIndex).withContext(`should be ${expectedGoToIndex}`).toBe(expectedGoToIndex);
- expect(component.resultSize)
- .withContext(`should be ${expectedResultSize}`)
- .toBe(expectedResultSize);
-
- expect(component.resourceInfoData).withContext('should be truthy').toBeTruthy();
- expect(component.resourceInfoData)
- .withContext(`should equal ${expectedResourceInfoData}`)
- .toEqual(expectedResourceInfoData);
+ expectToBe(component.goToIndex, expectedGoToIndex);
+ expectToBe(component.resultSize, expectedResultSize);
+ expectToEqual(component.resourceInfoData, expectedResourceInfoData);
});
});
});
@@ -557,10 +521,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expectedGoToIndex = 3;
expect(component.resourceInfoFormGroup).toBeTruthy();
- expect(component.resourceInfoFormGroup.controls['resourceInfoIndex']).toBeTruthy();
- expect(component.resourceInfoFormGroup.controls['resourceInfoIndex'].value)
- .withContext(`should equal ${expectedGoToIndex}`)
- .toEqual(expectedGoToIndex);
+ expectToBe(component.resourceInfoFormGroup.controls['resourceInfoIndex'].value, expectedGoToIndex);
});
it('... with empty index if none is given', () => {
@@ -571,10 +532,7 @@ describe('ResourceInfoComponent (DONE)', () => {
fixture.detectChanges();
expect(component.resourceInfoFormGroup).toBeTruthy();
- expect(component.resourceInfoFormGroup.controls['resourceInfoIndex']).toBeTruthy();
- expect(component.resourceInfoFormGroup.controls['resourceInfoIndex'].value)
- .withContext(`should equal ${expectedEmptyIndex}`)
- .toEqual(expectedEmptyIndex);
+ expectToBe(component.resourceInfoFormGroup.controls['resourceInfoIndex'].value, expectedEmptyIndex);
});
});
@@ -631,10 +589,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: nanValue,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('any string', () => {
@@ -647,10 +602,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: anyString,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('any array', () => {
@@ -663,10 +615,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: anyArray,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('empty object', () => {
@@ -679,10 +628,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: emptyObject,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('any object', () => {
@@ -695,10 +641,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: anyObject,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
});
@@ -715,10 +658,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: tenDigitNegativeInteger,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('no 1-digit negative integers (-1)', () => {
@@ -731,10 +671,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: oneDigitNegativeInteger,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('not 0', () => {
@@ -747,10 +684,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: zero,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('no 11-digit positive integers (12345678901)', () => {
@@ -763,10 +697,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: elevenDigitPositivInteger,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('no floating numbers (1.1)', () => {
@@ -779,10 +710,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: floatingNumber,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
it('no big floating numbers (1234567890.0123456789)', () => {
@@ -795,10 +723,7 @@ describe('ResourceInfoComponent (DONE)', () => {
actualValue: bigFloatingNumber,
};
- expect(errors['pattern']).toBeTruthy();
- expect(errors['pattern'])
- .withContext(`should equal ${expectedPatternError}`)
- .toEqual(expectedPatternError);
+ expectToEqual(errors['pattern'], expectedPatternError);
});
});
@@ -839,8 +764,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedError = { min: 1, actual: -1 };
- expect(errors['min']).toBeTruthy();
- expect(errors['min']).withContext(`should equal ${expectedError}`).toEqual(expectedError);
+ expectToEqual(errors['min'], expectedError);
});
it('min error == TRUE for 0', () => {
@@ -849,8 +773,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedError = { min: 1, actual: 0 };
- expect(errors['min']).toBeTruthy();
- expect(errors['min']).withContext(`should equal ${expectedError}`).toEqual(expectedError);
+ expectToEqual(errors['min'], expectedError);
});
it('min error == FALSE for 1', () => {
@@ -875,8 +798,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedError = { max: 5, actual: 6 };
- expect(errors['max']).toBeTruthy();
- expect(errors['max']).withContext(`should equal ${expectedError}`).toEqual(expectedError);
+ expectToEqual(errors['max'], expectedError);
});
it('max error == FALSE for value equals resultSize', () => {
@@ -900,14 +822,12 @@ describe('ResourceInfoComponent (DONE)', () => {
it('... should return index position of a given `resourceId` in given search response', () => {
const expectedResponseClone = JSON.parse(JSON.stringify(expectedSearchResponseWithQuery));
- expect(
- (component as any)._findIndexPositionInSearchResultsById(expectedResourceId, expectedResponseClone)
- ).toBeTruthy();
- expect(
- (component as any)._findIndexPositionInSearchResultsById(expectedResourceId, expectedResponseClone)
- )
- .withContext('should be 2')
- .toBe(2);
+ const actualIndex = (component as any)._findIndexPositionInSearchResultsById(
+ expectedResourceId,
+ expectedResponseClone
+ );
+
+ expectToBe(actualIndex, 2);
});
it('... should return -1 if resource id is not found in given search response', () => {
@@ -921,12 +841,12 @@ describe('ResourceInfoComponent (DONE)', () => {
otherResponseClone.data.subjects.slice(sliceIndex + 1, otherResponseClone.data.subjects.length)
);
- expect(
- (component as any)._findIndexPositionInSearchResultsById(expectedResourceId, otherResponseClone)
- ).toBeTruthy();
- expect((component as any)._findIndexPositionInSearchResultsById(expectedResourceId, otherResponseClone))
- .withContext('should be -1')
- .toBe(-1);
+ const actualIndex = (component as any)._findIndexPositionInSearchResultsById(
+ expectedResourceId,
+ otherResponseClone
+ );
+
+ expectToBe(actualIndex, -1);
});
});
@@ -1093,7 +1013,7 @@ describe('ResourceInfoComponent (DONE)', () => {
component.resourceInfoData.searchResults = null;
component.navigateToSearchPanel();
- expect(component.resourceInfoData.searchResults).toBeNull();
+ expectToBe(component.resourceInfoData.searchResults, null);
expectSpyCall(navigationSpy, 1, [expectedRoute, expectedParams]);
});
@@ -1110,9 +1030,7 @@ describe('ResourceInfoComponent (DONE)', () => {
component.navigateToSearchPanel();
expect(component.resourceInfoData.searchResults).toBeTruthy();
- expect(component.resourceInfoData.searchResults.query)
- .withContext('should be empty string (falsy)')
- .toBeFalsy();
+ expectToBe(component.resourceInfoData.searchResults.query, '');
expectSpyCall(navigationSpy, 1, [expectedRoute, expectedParams]);
});
});
@@ -1149,9 +1067,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(component.resourceInfoData.searchResults).toBeTruthy();
expect(component.resourceInfoData.searchResults.query).toBeTruthy();
- expect(typeof component.resourceInfoData.searchResults.query)
- .withContext(`should be string`)
- .toBe('string');
+ expectToBe(typeof component.resourceInfoData.searchResults.query, 'string');
expectSpyCall(navigationSpy, 1, [expectedRoute, expectedParams]);
});
});
@@ -1183,9 +1099,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(component.resourceInfoData.searchResults).toBeTruthy();
expect(component.resourceInfoData.searchResults.query).toBeTruthy();
- expect(typeof component.resourceInfoData.searchResults.query)
- .withContext(`should be object`)
- .toBe('object');
+ expectToBe(typeof component.resourceInfoData.searchResults.query, 'object');
expectSpyCall(navigationSpy, 1, [expectedRoute, expectedParams]);
});
});
@@ -1262,7 +1176,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(iconDes[0].children[0]).toBeTruthy();
expect(iconDes[0].children[0].classes).toBeTruthy();
- expect(iconDes[0].children[0].classes['fa-arrow-left']).toBeTrue();
+ expectToBe(iconDes[0].children[0].classes['fa-arrow-left'], true);
});
it('... should display innerHTML text on first div button', () => {
@@ -1272,8 +1186,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedText = 'Zur Suche';
- expect(spanEl.innerText).toBeTruthy();
- expect(spanEl.innerText).withContext(`should be ${expectedText}`).toBe(expectedText);
+ expectToBe(spanEl.innerText, expectedText);
});
it('... should display bold, small, muted text in second div', () => {
@@ -1286,8 +1199,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(strongEl).toHaveClass('text-muted');
expect(strongEl).toHaveClass('small');
- expect(strongEl.innerText).toBeTruthy();
- expect(strongEl.innerText).withContext(`should be ${expectedText}`).toBe(expectedText);
+ expectToBe(strongEl.innerText, expectedText);
});
it('... should display query in span in second div', () => {
@@ -1299,10 +1211,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const spanDes = getAndExpectDebugElementByCss(divDes[1], 'span', 1, 1);
const spanEl = spanDes[0].nativeElement;
- expect(spanEl.innerText).toBeTruthy();
- expect(spanEl.innerText)
- .withContext(`should be ${expectedQuery}`)
- .toBe(jsonPipe.transform(expectedQuery));
+ expectToBe(spanEl.innerText, jsonPipe.transform(expectedQuery));
});
it('... should display `---` without query in span in second div', () => {
@@ -1316,8 +1225,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedText = '---';
- expect(spanEl.innerText).toBeTruthy();
- expect(spanEl.innerText).withContext(`should be ${expectedText}`).toBe(expectedText);
+ expectToBe(spanEl.innerText, expectedText);
});
});
@@ -1406,7 +1314,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const iconDes = getAndExpectDebugElementByCss(strongDes[0], 'fa-icon', 1, 1);
expect(iconDes[0].children[0]).toBeTruthy();
expect(iconDes[0].children[0].classes).toBeTruthy();
- expect(iconDes[0].children[0].classes['fa-chevron-left']).toBeTrue();
+ expectToBe(iconDes[0].children[0].classes['fa-chevron-left'], true);
});
it('... should point to previous resource in span in strong element', () => {
@@ -1427,10 +1335,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedIndex = component.resourceInfoData.resources.previous.displayIndex; // = 2
const expectedInnerText = `Vorheriges Ergebnis (${expectedIndex}/${expectedResultSize})`;
- expect(spanEl.innerText).toBeTruthy();
- expect(spanEl.innerText)
- .withContext(`should be ${expectedInnerText}`)
- .toBe(expectedInnerText);
+ expectToBe(spanEl.innerText, expectedInnerText);
});
it('... should have two divs.single-line in second div', () => {
@@ -1465,8 +1370,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const spanEl0 = spanDes[0].nativeElement;
const title = component.resourceInfoData.resources.previous.title; // = Nelson 1974
- expect(spanEl0.innerText).toBeTruthy();
- expect(spanEl0.innerText).withContext(`should be ${title}`).toBe(title);
+ expectToBe(spanEl0.innerText, title);
});
it('... should display previous subtitle in second div.single-line', () => {
@@ -1485,8 +1389,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const spanEl1 = spanDes[1].nativeElement;
const subTitle = component.resourceInfoData.resources.previous.subtitle; // = Bibliografie
- expect(spanEl1.innerText).toBeTruthy();
- expect(spanEl1.innerText).withContext(`should be ${subTitle}`).toBe(subTitle);
+ expectToBe(spanEl1.innerText, subTitle);
});
});
@@ -1503,10 +1406,7 @@ describe('ResourceInfoComponent (DONE)', () => {
});
it('... should have current.displayIndex === 1', () => {
- expect(component.resourceInfoData.resources.current.displayIndex).toBeTruthy();
- expect(component.resourceInfoData.resources.current.displayIndex)
- .withContext('should be 1')
- .toBe(1);
+ expectToBe(component.resourceInfoData.resources.current.displayIndex, 1);
});
it('... should have list-group-item-danger class', () => {
@@ -1556,7 +1456,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(iconDes[0].children[0]).toBeTruthy();
expect(iconDes[0].children[0].classes).toBeTruthy();
- expect(iconDes[0].children[0].classes['fa-circle-xmark']).toBeTrue();
+ expectToBe(iconDes[0].children[0].classes['fa-circle-xmark'], true);
});
it('... should have two empty divs.single-line in second div', () => {
@@ -1581,15 +1481,8 @@ describe('ResourceInfoComponent (DONE)', () => {
const whiteSpace = '\xA0'; // Hex code for a non-breaking space ' '
- expect(spanEl0.innerText).toBeTruthy();
- expect(spanEl0.innerText)
- .withContext(`should be non-breaking whiteSpace ${whiteSpace}`)
- .toBe(whiteSpace);
-
- expect(spanEl1.innerText).toBeTruthy();
- expect(spanEl1.innerText)
- .withContext(`should be non-breaking whiteSpace ${whiteSpace}`)
- .toBe(whiteSpace);
+ expectToBe(spanEl0.innerText, whiteSpace);
+ expectToBe(spanEl1.innerText, whiteSpace);
});
});
});
@@ -1650,10 +1543,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedIndex = component.resourceInfoData.resources.current.displayIndex; // = 3
const expectedInnerText = `Angezeigtes Ergebnis (${expectedIndex}/${expectedResultSize})`;
- expect(spanEl.innerText).toBeTruthy();
- expect(spanEl.innerText)
- .withContext(`should be ${expectedInnerText}`)
- .toBe(expectedInnerText);
+ expectToBe(spanEl.innerText, expectedInnerText);
});
it('... should contain one div with button and an input in form > div.input-group', () => {
@@ -1687,22 +1577,10 @@ describe('ResourceInfoComponent (DONE)', () => {
1
);
- // FormControlName='resourceInfoIndex'
- expect(inputDes[0].attributes['formControlName']).toBeTruthy();
- expect(inputDes[0].attributes['formControlName'])
- .withContext('should be resourceInfoIndex')
- .toBe('resourceInfoIndex');
-
- // Type='number'
- expect(inputDes[0].attributes['type']).toBeTruthy();
- expect(inputDes[0].attributes['type']).withContext('should be number').toBe('number');
-
- // Size=4
- expect(inputDes[0].attributes['size']).toBeTruthy();
- expect(inputDes[0].attributes['size']).withContext('should be 4').toBe('4');
- // Step=1
- expect(inputDes[0].attributes['step']).toBeTruthy();
- expect(inputDes[0].attributes['step']).withContext('should be 1').toBe('1');
+ expectToBe(inputDes[0].attributes['formControlName'], 'resourceInfoIndex');
+ expectToBe(inputDes[0].attributes['type'], 'number');
+ expectToBe(inputDes[0].attributes['size'], '4');
+ expectToBe(inputDes[0].attributes['step'], '1');
});
describe('button', () => {
@@ -1715,15 +1593,9 @@ describe('ResourceInfoComponent (DONE)', () => {
);
const buttonEl = buttonDes[0].nativeElement;
- // Type='submit'
- expect(buttonDes[0].attributes['type']).toBeTruthy();
- expect(buttonDes[0].attributes['type']).withContext('should be submit').toBe('submit');
-
- // Class=btn
+ expectToBe(buttonDes[0].attributes['type'], 'submit');
expect(buttonEl).toHaveClass('btn');
-
- // Disabled = true
- expect(buttonEl.disabled).toBeTrue();
+ expectToBe(buttonEl.disabled, true);
});
it('... should display innerHTML text', () => {
@@ -1737,8 +1609,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedText = 'Gehe zu';
- expect(buttonEl.innerText).toBeTruthy();
- expect(buttonEl.innerText).withContext(`should be ${expectedText}`).toBe(expectedText);
+ expectToBe(buttonEl.innerText, expectedText);
});
it('... should have btn-outline-success class when form is valid', () => {
@@ -1795,13 +1666,11 @@ describe('ResourceInfoComponent (DONE)', () => {
const resourceInfoIndex = component.resourceInfoFormGroup.controls['resourceInfoIndex'];
// Input index is current.displayIndex
- expect(resourceInfoIndex.value)
- .withContext(
- `should be ${component.resourceInfoData.resources.current.displayIndex}`
- )
- .toBe(component.resourceInfoData.resources.current.displayIndex);
- // Disabled = true
- expect(buttonEl.disabled).toBeTrue();
+ expectToBe(
+ resourceInfoIndex.value,
+ component.resourceInfoData.resources.current.displayIndex
+ );
+ expectToBe(buttonEl.disabled, true);
});
it('... should be disabled when form is not valid', () => {
@@ -1825,7 +1694,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(component.resourceInfoFormGroup.invalid).toBeTruthy();
// Disabled = true
- expect(buttonEl.disabled).toBeTrue();
+ expectToBe(buttonEl.disabled, true);
});
it('... should be enabled when input index is not current.displayIndex and form is valid', () => {
@@ -1849,14 +1718,10 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(component.resourceInfoFormGroup.invalid).toBeFalsy();
// Input index is different from current.displayIndex
- expect(resourceInfoIndex.value)
- .withContext(
- `should not be ${component.resourceInfoData.resources.current.displayIndex}`
- )
- .not.toBe(component.resourceInfoData.resources.current.displayIndex);
-
- // Disabled = false
- expect(buttonEl.disabled).toBeFalse();
+ expect(resourceInfoIndex.value).not.toBe(
+ component.resourceInfoData.resources.current.displayIndex
+ );
+ expectToBe(buttonEl.disabled, false);
});
it('... should not be able to navigate to resource by index when button is disabled', fakeAsync(() => {
@@ -1872,7 +1737,8 @@ describe('ResourceInfoComponent (DONE)', () => {
// ---------------------------
// DISABLED: case 1
// Input index is current.displayIndex
- expect(resourceInfoIndex.value).toBe(
+ expectToBe(
+ resourceInfoIndex.value,
component.resourceInfoData.resources.current.displayIndex
);
@@ -1881,7 +1747,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(component.resourceInfoFormGroup.invalid).toBeFalsy();
// Disabled = true
- expect(buttonEl.disabled).toBeTrue();
+ expectToBe(buttonEl.disabled, true);
// Trigger click on button with click helper & wait for changes
clickAndAwaitChanges(buttonDes[0], fixture);
@@ -1901,7 +1767,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(component.resourceInfoFormGroup.invalid).toBeTruthy();
// Disabled = true
- expect(buttonEl.disabled).toBeTrue();
+ expectToBe(buttonEl.disabled, true);
// Trigger click on button with click helper & wait for changes
clickAndAwaitChanges(buttonDes[0], fixture);
@@ -1936,7 +1802,7 @@ describe('ResourceInfoComponent (DONE)', () => {
expect(component.resourceInfoFormGroup.invalid).toBeFalsy();
// Button.disabled = false
- expect(buttonEl.disabled).toBeFalse();
+ expectToBe(buttonEl.disabled, false);
// Trigger click on button with click helper & wait for changes
clickAndAwaitChanges(buttonDes[0], fixture);
@@ -2032,7 +1898,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const iconDes = getAndExpectDebugElementByCss(strongDes[0], 'fa-icon', 1, 1);
expect(iconDes[0].children[0]).toBeTruthy();
expect(iconDes[0].children[0].classes).toBeTruthy();
- expect(iconDes[0].children[0].classes['fa-chevron-right']).toBeTrue();
+ expectToBe(iconDes[0].children[0].classes['fa-chevron-right'], true);
});
it('... should point to previous resource in span in strong element', () => {
@@ -2053,10 +1919,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const expectedIndex = component.resourceInfoData.resources.next.displayIndex; // = 4
const expectedInnerText = `Nächstes Ergebnis (${expectedIndex}/${expectedResultSize})`;
- expect(spanEl.innerText).toBeTruthy();
- expect(spanEl.innerText)
- .withContext(`should be ${expectedInnerText}`)
- .toBe(expectedInnerText);
+ expectToBe(spanEl.innerText, expectedInnerText);
});
it('... should have two divs.single-line in second div', () => {
@@ -2091,8 +1954,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const spanEl0 = spanDes[0].nativeElement;
const title = component.resourceInfoData.resources.next.title; // = BrownJ 2014
- expect(spanEl0.innerText).toBeTruthy();
- expect(spanEl0.innerText).withContext(`should be ${title}`).toBe(title);
+ expectToBe(spanEl0.innerText, title);
});
it('... should display next subtitle in second div.single-line', () => {
@@ -2112,8 +1974,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const spanEl1 = spanDes[1].nativeElement;
const subTitle = component.resourceInfoData.resources.next.subtitle; // = Bibliografie
- expect(spanEl1.innerText).toBeTruthy();
- expect(spanEl1.innerText).withContext(`should be ${subTitle}`).toBe(subTitle);
+ expectToBe(spanEl1.innerText, subTitle);
});
});
@@ -2130,10 +1991,7 @@ describe('ResourceInfoComponent (DONE)', () => {
});
it('... should have current.displayIndex === resultSize', () => {
- expect(component.resourceInfoData.resources.current.displayIndex).toBeTruthy();
- expect(component.resourceInfoData.resources.current.displayIndex)
- .withContext(`should be ${component.resultSize}`)
- .toBe(component.resultSize);
+ expectToBe(component.resourceInfoData.resources.current.displayIndex, component.resultSize);
});
it('... should have list-group-item-danger class', () => {
@@ -2177,7 +2035,7 @@ describe('ResourceInfoComponent (DONE)', () => {
const iconDes = getAndExpectDebugElementByCss(strongDes[0], 'fa-icon', 1, 1);
expect(iconDes[0].children[0]).toBeTruthy();
expect(iconDes[0].children[0].classes).toBeTruthy();
- expect(iconDes[0].children[0].classes['fa-circle-xmark']).toBeTrue();
+ expectToBe(iconDes[0].children[0].classes['fa-circle-xmark'], true);
});
it('... should have two empty divs.single-line in second div', () => {
@@ -2202,15 +2060,8 @@ describe('ResourceInfoComponent (DONE)', () => {
const whiteSpace = '\xA0'; // Hex code for a non-breaking space ' '
- expect(spanEl0.innerText).withContext(`should be truthy`).toBeTruthy();
- expect(spanEl0.innerText)
- .withContext(`should be non-breaking whiteSpace ${whiteSpace}`)
- .toBe(whiteSpace);
-
- expect(spanEl1.innerText).withContext(`should be truthy`).toBeTruthy();
- expect(spanEl1.innerText)
- .withContext(`should be non-breaking whiteSpace ${whiteSpace}`)
- .toBe(whiteSpace);
+ expectToBe(spanEl0.innerText, whiteSpace);
+ expectToBe(spanEl1.innerText, whiteSpace);
});
});
});
@@ -2224,8 +2075,8 @@ describe('ResourceInfoComponent (DONE)', () => {
const aDe = getAndExpectDebugElementByCss(compDe, 'div.card-footer a', 1, 1);
const aEl = aDe[0].nativeElement;
- expect(aEl.href).withContext(`should be ${expectedHref}`).toBe(expectedHref);
- expect(aEl.innerText).withContext(`should be ${expectedInnerText}`).toBe(expectedInnerText);
+ expectToBe(aEl.href, expectedHref);
+ expectToBe(aEl.innerText, expectedInnerText);
});
});
});
diff --git a/src/app/side-info/structure-info/structure-info.component.spec.ts b/src/app/side-info/structure-info/structure-info.component.spec.ts
index 5eb40b2be..54ef7ba3f 100644
--- a/src/app/side-info/structure-info/structure-info.component.spec.ts
+++ b/src/app/side-info/structure-info/structure-info.component.spec.ts
@@ -2,7 +2,7 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
-import { getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectToBe, expectToContain, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { METADATA } from '@awg-core/core-data';
import { MetaSectionTypes, MetaStructure } from '@awg-core/core-models';
@@ -54,15 +54,12 @@ describe('StructureInfoComponent (DONE)', () => {
it('... injected service should use provided mockValue', () => {
const coreService = TestBed.inject(CoreService);
- expect(mockCoreService === coreService).toBe(true);
+ expectToBe(mockCoreService === coreService, true);
});
describe('BEFORE initial data binding', () => {
it('... should have structureInfoHeader', () => {
- expect(component.structureInfoHeader).toBeDefined();
- expect(component.structureInfoHeader)
- .withContext(`should be ${expectedStructureInfoHeader}`)
- .toBe(expectedStructureInfoHeader);
+ expectToBe(component.structureInfoHeader, expectedStructureInfoHeader);
});
describe('#provideMetaData()', () => {
@@ -94,25 +91,22 @@ describe('StructureInfoComponent (DONE)', () => {
const headerDes = getAndExpectDebugElementByCss(compDe, 'h5#awg-structure-info-header', 1, 1);
const headerEl = headerDes[0].nativeElement;
- expect(headerEl).toBeDefined();
- expect(headerEl.textContent).toBeFalsy();
+ expectToBe(headerEl.textContent, '');
});
it('... should not render author information yet', () => {
const authorDes = getAndExpectDebugElementByCss(compDe, 'span.awg-structure-info-author a', 1, 1);
const authorEl = authorDes[0].nativeElement;
- expect(authorEl).toBeDefined();
- expect(authorEl.href).toBeFalsy();
- expect(authorEl.innerHTML).toBeFalsy();
+ expectToBe(authorEl.href, '');
+ expectToBe(authorEl.innerHTML, '');
});
it('... should not render last modification date yet', () => {
const dateDes = getAndExpectDebugElementByCss(compDe, 'span#awg-structure-info-lastmodified', 1, 1);
const dateEl = dateDes[0].nativeElement;
- expect(dateEl).toBeDefined();
- expect(dateEl.textContent).toBeFalsy();
+ expectToBe(dateEl.textContent, '');
});
});
});
@@ -132,10 +126,7 @@ describe('StructureInfoComponent (DONE)', () => {
});
it('... should return structureMetaData', () => {
- expect(component.structureMetaData).toBeDefined();
- expect(component.structureMetaData)
- .withContext(`should be ${expectedStructureMetaData}`)
- .toBe(expectedStructureMetaData);
+ expectToEqual(component.structureMetaData, expectedStructureMetaData);
});
});
@@ -144,10 +135,7 @@ describe('StructureInfoComponent (DONE)', () => {
const headerDes = getAndExpectDebugElementByCss(compDe, 'h5#awg-structure-info-header', 1, 1);
const headerEl = headerDes[0].nativeElement;
- expect(headerEl).toBeDefined();
- expect(headerEl.textContent)
- .withContext(`should be ${expectedStructureInfoHeader}`)
- .toBe(expectedStructureInfoHeader);
+ expectToBe(headerEl.textContent, expectedStructureInfoHeader);
});
it('... should render author information', () => {
@@ -156,9 +144,8 @@ describe('StructureInfoComponent (DONE)', () => {
const authorDes = getAndExpectDebugElementByCss(compDe, 'span.awg-structure-info-author a', 1, 1);
const authorEl = authorDes[0].nativeElement;
- expect(authorEl).toBeDefined();
- expect(authorEl.href).withContext(`should be ${expectedAuthor.homepage}`).toBe(expectedAuthor.homepage);
- expect(authorEl.innerHTML).withContext(`should be ${expectedAuthor.name}`).toBe(expectedAuthor.name);
+ expectToBe(authorEl.href, expectedAuthor.homepage);
+ expectToBe(authorEl.innerHTML, expectedAuthor.name);
});
it('... should render last modification date', () => {
@@ -167,10 +154,7 @@ describe('StructureInfoComponent (DONE)', () => {
const lastmodDes = getAndExpectDebugElementByCss(compDe, 'span#awg-structure-info-lastmodified', 1, 1);
const lastmodEl = lastmodDes[0].nativeElement;
- expect(lastmodEl.textContent).toBeDefined();
- expect(lastmodEl.textContent)
- .withContext(`should contain ${expectedLastModified}`)
- .toContain(expectedLastModified);
+ expectToContain(lastmodEl.textContent, expectedLastModified);
});
});
});
diff --git a/src/app/views/contact-view/contact-view.component.spec.ts b/src/app/views/contact-view/contact-view.component.spec.ts
index b9beb02be..12b1cc71e 100644
--- a/src/app/views/contact-view/contact-view.component.spec.ts
+++ b/src/app/views/contact-view/contact-view.component.spec.ts
@@ -9,6 +9,9 @@ import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import {
expectSpyCall,
+ expectToBe,
+ expectToContain,
+ expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -93,43 +96,27 @@ describe('ContactViewComponent (DONE)', () => {
it('... injected service should use provided mockValue', () => {
const coreService = TestBed.inject(CoreService);
- expect(mockCoreService === coreService).toBe(true);
+ expectToBe(mockCoreService === coreService, true);
});
describe('BEFORE initial data binding', () => {
it('... should have imprint title and id', () => {
- expect(component.imprintTitle).toBeDefined();
- expect(component.imprintTitle).withContext(`should be ${expectedImprintTitle}`).toBe(expectedImprintTitle);
-
- expect(component.imprintId).toBeDefined();
- expect(component.imprintId).withContext(`should be ${expectedImprintId}`).toBe(expectedImprintId);
+ expectToBe(component.imprintTitle, expectedImprintTitle);
+ expectToBe(component.imprintId, expectedImprintId);
});
it('... should have citation title and id', () => {
- expect(component.citationTitle).toBeDefined();
- expect(component.citationTitle)
- .withContext(`should be ${expectedCitationTitle}`)
- .toBe(expectedCitationTitle);
-
- expect(component.citationId).toBeDefined();
- expect(component.citationId).withContext(`should be ${expectedCitationId}`).toBe(expectedCitationId);
+ expectToBe(component.citationTitle, expectedCitationTitle);
+ expectToBe(component.citationId, expectedCitationId);
});
it('... should have documentation title and id', () => {
- expect(component.documentationTitle).toBeDefined();
- expect(component.documentationTitle)
- .withContext(`should be ${expectedDocumentationTitle}`)
- .toBe(expectedDocumentationTitle);
-
- expect(component.documentationId).toBeDefined();
- expect(component.documentationId)
- .withContext(`should be ${expectedDocumentationId}`)
- .toBe(expectedDocumentationId);
+ expectToBe(component.documentationTitle, expectedDocumentationTitle);
+ expectToBe(component.documentationId, expectedDocumentationId);
});
it('... should have dateFormat', () => {
- expect(component.dateFormat).toBeDefined();
- expect(component.dateFormat).withContext(`should be ${expectedDateFormat}`).toBe(expectedDateFormat);
+ expectToBe(component.dateFormat, expectedDateFormat);
});
it('... should not have metadata nor `today`', () => {
@@ -210,16 +197,10 @@ describe('ContactViewComponent (DONE)', () => {
const dateEl1 = dateDes[1].nativeElement;
// Check output
- expect(versionEl).toBeDefined();
- expect(versionEl.textContent).withContext('should be empty string').toBe('');
-
- expect(releaseEl).toBeDefined();
- expect(releaseEl.textContent).withContext('should be empty string').toBe('');
-
- expect(dateEl0).toBeDefined();
- expect(dateEl0.textContent).withContext('should be empty string').toBe('');
- expect(dateEl1).toBeDefined();
- expect(dateEl1.textContent).withContext('should be empty string').toBe('');
+ expectToBe(versionEl.textContent, '');
+ expectToBe(releaseEl.textContent, '');
+ expectToBe(dateEl0.textContent, '');
+ expectToBe(dateEl1.textContent, '');
});
});
});
@@ -253,8 +234,8 @@ describe('ContactViewComponent (DONE)', () => {
it('... should have triggered `router.navigate`', () => {
expect(navigationSpy).toHaveBeenCalled();
- expect(navigationSpy.calls.any()).withContext('has any calls').toEqual(true);
- expect(navigationSpy.calls.count()).withContext('has been called only once').toEqual(1);
+ expectToBe(navigationSpy.calls.any(), true);
+ expectToBe(navigationSpy.calls.count(), 1);
});
it('... should tell ROUTER to navigate to `contactInfo` outlet', () => {
@@ -266,8 +247,7 @@ describe('ContactViewComponent (DONE)', () => {
expect(navArgs).toBeDefined();
expect(navArgs[0]).toBeDefined();
- expect(outletRoute).toBeDefined();
- expect(outletRoute).withContext(`should be: ${expectedRoute}`).toBe(expectedRoute);
+ expectToBe(outletRoute, expectedRoute);
expect(navigationSpy).toHaveBeenCalledWith(navArgs[0], navArgs[1]);
});
@@ -277,8 +257,7 @@ describe('ContactViewComponent (DONE)', () => {
const navExtras = navArgs[1];
expect(navExtras).toBeDefined();
- expect(navExtras.preserveFragment).toBeDefined();
- expect(navExtras.preserveFragment).toBeTrue();
+ expectToBe(navExtras.preserveFragment, true);
expect(navigationSpy).toHaveBeenCalledWith(navArgs[0], navArgs[1]);
});
});
@@ -289,22 +268,14 @@ describe('ContactViewComponent (DONE)', () => {
});
it('... should return metadata', () => {
- expect(component.pageMetaData).toBeDefined();
- expect(component.pageMetaData)
- .withContext(`should be: ${expectedPageMetaData}`)
- .toBe(expectedPageMetaData);
-
- expect(component.contactMetaData).toBeDefined();
- expect(component.contactMetaData)
- .withContext(`should be: ${expectedContactMetaData}`)
- .toBe(expectedContactMetaData);
+ expectToEqual(component.pageMetaData, expectedPageMetaData);
+ expectToEqual(component.contactMetaData, expectedContactMetaData);
});
});
it('... should have `today`', () => {
expectSpyCall(dateSpy, 1);
- expect(component.today).toBeDefined();
- expect(component.today).withContext(`should be ${expectedToday}`).toBe(expectedToday);
+ expectToBe(component.today, expectedToday);
});
describe('VIEW', () => {
@@ -312,31 +283,14 @@ describe('ContactViewComponent (DONE)', () => {
const headingDes = getAndExpectDebugElementByDirective(compDe, HeadingStubComponent, 3, 3);
const headingCmps = headingDes.map(de => de.injector.get(HeadingStubComponent) as HeadingStubComponent);
- expect(headingCmps[0].title).toBeTruthy();
- expect(headingCmps[0].title)
- .withContext(`should have title: ${expectedCitationTitle}`)
- .toBe(expectedCitationTitle);
-
- expect(headingCmps[0].id).toBeTruthy();
- expect(headingCmps[0].id).withContext(`should have id: ${expectedCitationId}`).toBe(expectedCitationId);
-
- expect(headingCmps[1].title).toBeTruthy();
- expect(headingCmps[1].title)
- .withContext(`should have title: ${expectedDocumentationTitle}`)
- .toBe(expectedDocumentationTitle);
-
- expect(headingCmps[1].id).toBeTruthy();
- expect(headingCmps[1].id)
- .withContext(`should have id: ${expectedDocumentationId}`)
- .toBe(expectedDocumentationId);
+ expectToBe(headingCmps[0].title, expectedCitationTitle);
+ expectToBe(headingCmps[0].id, expectedCitationId);
- expect(headingCmps[2].title).toBeTruthy();
- expect(headingCmps[2].title)
- .withContext(`should have title: ${expectedImprintTitle}`)
- .toBe(expectedImprintTitle);
+ expectToBe(headingCmps[1].title, expectedDocumentationTitle);
+ expectToBe(headingCmps[1].id, expectedDocumentationId);
- expect(headingCmps[2].id).toBeTruthy();
- expect(headingCmps[2].id).withContext(`should have id: ${expectedImprintId}`).toBe(expectedImprintId);
+ expectToBe(headingCmps[2].title, expectedImprintTitle);
+ expectToBe(headingCmps[2].id, expectedImprintId);
});
it('... should render `version`, `versionReleaseDate` and `today`', () => {
@@ -355,20 +309,10 @@ describe('ContactViewComponent (DONE)', () => {
const pipedToday = datePipe.transform(expectedToday, expectedDateFormat);
// Check output
- expect(versionEl).toBeDefined();
- expect(versionEl.textContent)
- .withContext(`should contain ${expectedPageMetaData.version}`)
- .toContain(expectedPageMetaData.version);
-
- expect(releaseEl).toBeDefined();
- expect(releaseEl.textContent)
- .withContext(`should contain ${expectedPageMetaData.versionReleaseDate}`)
- .toContain(expectedPageMetaData.versionReleaseDate);
-
- expect(dateEl0).toBeDefined();
- expect(dateEl0.textContent).withContext(`should contain ${pipedToday}`).toContain(pipedToday);
- expect(dateEl1).toBeDefined();
- expect(dateEl1.textContent).withContext(`should contain ${pipedToday}`).toContain(pipedToday);
+ expectToContain(versionEl.textContent, expectedPageMetaData.version);
+ expectToContain(releaseEl.textContent, expectedPageMetaData.versionReleaseDate);
+ expectToContain(dateEl0.textContent, pipedToday);
+ expectToContain(dateEl1.textContent, pipedToday);
});
});
});
diff --git a/src/app/views/data-view/data-outlets/bibliography/bibliography-detail/bibliography-detail.component.spec.ts b/src/app/views/data-view/data-outlets/bibliography/bibliography-detail/bibliography-detail.component.spec.ts
index 8c4ad9603..96b49a848 100644
--- a/src/app/views/data-view/data-outlets/bibliography/bibliography-detail/bibliography-detail.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/bibliography/bibliography-detail/bibliography-detail.component.spec.ts
@@ -2,12 +2,14 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { Observable, of as observableOf } from 'rxjs';
+import { expectToBe } from '@testing/expect-helper';
+
import { ConversionService } from '@awg-core/services';
import { ResourceFullResponseJson } from '@awg-shared/api-objects';
+import { BibliographyFormatPipe } from '@awg-views/data-view/data-outlets/bibliography//bibliography-format.pipe';
+import { BibEntry } from '@awg-views/data-view/data-outlets/bibliography/bibliography-entry.model';
import { BibliographyService } from '@awg-views/data-view/services';
-import { BibEntry } from '../bibliography-entry.model';
-import { BibliographyFormatPipe } from '../bibliography-format.pipe';
import { BibliographyDetailComponent } from './bibliography-detail.component';
describe('BibliographyDetailComponent', () => {
@@ -73,8 +75,7 @@ describe('BibliographyDetailComponent', () => {
});
it('... should have objId input', () => {
- expect(component.objId).toBeTruthy();
- expect(component.objId).withContext(`should be ${expectedObjId}`).toBe(expectedObjId);
+ expectToBe(component.objId, expectedObjId);
});
});
});
diff --git a/src/app/views/data-view/data-outlets/bibliography/bibliography.component.spec.ts b/src/app/views/data-view/data-outlets/bibliography/bibliography.component.spec.ts
index af8f66115..989974d92 100644
--- a/src/app/views/data-view/data-outlets/bibliography/bibliography.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/bibliography/bibliography.component.spec.ts
@@ -5,6 +5,8 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { Observable, of as observableOf } from 'rxjs';
import Spy = jasmine.Spy;
+import { expectToBe } from '@testing/expect-helper';
+
import { SearchResponseJson, SubjectItemJson } from '@awg-shared/api-objects';
import { BibliographyService } from '@awg-views/data-view/services';
@@ -76,6 +78,6 @@ describe('BibliographyComponent', () => {
});
it('... injected bibliography service should use provided mockValue', () => {
- expect(bibliographyService === mockBibliographyService).toBe(true);
+ expectToBe(bibliographyService === mockBibliographyService, true);
});
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-header/resource-detail-header.component.spec.ts b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-header/resource-detail-header.component.spec.ts
index 4f0658a34..4a4e66097 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-header/resource-detail-header.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-header/resource-detail-header.component.spec.ts
@@ -4,6 +4,8 @@ import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/cor
import { clickAndAwaitChanges } from '@testing/click-helper';
import {
expectSpyCall,
+ expectToBe,
+ expectToContain,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -84,11 +86,9 @@ describe('ResourceDetailHtmlHeaderComponent (DONE)', () => {
it('... should contain span in h2.title with compile html component with no inner html yet', () => {
const titleDe = getAndExpectDebugElementByCss(compDe, 'div.resource-title > h2.title', 1, 1);
- // Find DebugElements with an attached CompileHtmlComponent
const htmlDes = getAndExpectDebugElementByDirective(titleDe[0], CompileHtmlComponent, 1, 1);
- expect(htmlDes[0].name).toBe('span');
+ expectToBe(htmlDes[0].name, 'span');
- // Find anchor links of CompileHtmlComponent
getAndExpectDebugElementByCss(htmlDes[0], 'a', 0, 0);
});
@@ -96,8 +96,7 @@ describe('ResourceDetailHtmlHeaderComponent (DONE)', () => {
const rLinkDe = getAndExpectDebugElementByCss(compDe, 'div.col-lg-8 > div.resource-link', 1, 1);
const rLinkEl = rLinkDe[0].nativeElement;
- expect(rLinkEl.textContent).toBeDefined();
- expect(rLinkEl.textContent).withContext(`should contain ' API-Request: '`).toContain(' API-Request: ');
+ expectToContain(rLinkEl.textContent, ' API-Request: ');
});
it('... should contain one table.resource-header-table', () => {
@@ -127,33 +126,25 @@ describe('ResourceDetailHtmlHeaderComponent (DONE)', () => {
fixture.detectChanges();
});
- it('... should have `header` or `resourceUrl` inputs', () => {
- expect(component.header).toBeDefined();
- expect(component.header).withContext(`should be ${expectedHeader}`).toBe(expectedHeader);
-
- expect(component.resourceUrl).toBeDefined();
- expect(component.resourceUrl).withContext(`should be ${expectedResourceUrl}`).toBe(expectedResourceUrl);
+ it('... should have `header` and `resourceUrl` inputs', () => {
+ expectToBe(component.header, expectedHeader);
+ expectToBe(component.resourceUrl, expectedResourceUrl);
});
describe('VIEW', () => {
it('... should render header title in compile html component span', () => {
const expectedTitle = 'Op. 28: Skizzen zu einem "1. Satz" (später 2. Satz [M 330])';
- // Find DebugElements with an attached CompileHtmlComponent
const htmlDes = getAndExpectDebugElementByDirective(compDe, CompileHtmlComponent, 1, 1);
const htmlEl = htmlDes[0].nativeElement;
- expect(htmlDes[0].name).toBeDefined();
- expect(htmlDes[0].name).withContext(`should be 'span'`).toBe('span');
-
- expect(htmlEl.textContent).toBeDefined();
- expect(htmlEl.textContent).withContext(`should contain ${expectedTitle}`).toContain(expectedTitle);
+ expectToBe(htmlDes[0].name, 'span');
+ expectToContain(htmlEl.textContent, expectedTitle);
});
it('... should have 3 anchor links in compile html component span', () => {
- // Find DebugElements with an attached CompileHtmlComponent
const htmlDes = getAndExpectDebugElementByDirective(compDe, CompileHtmlComponent, 1, 1);
- // Find anchor links of CompileHtmlComponent
+
getAndExpectDebugElementByCss(htmlDes[0], 'a', 3, 3);
});
@@ -172,33 +163,17 @@ describe('ResourceDetailHtmlHeaderComponent (DONE)', () => {
const lastModEl = lastModDes[0].nativeElement;
// Check output
- expect(tdEl.textContent).toBeTruthy();
- expect(tdEl.textContent)
- .withContext(`should contain ${expectedHeader.objID}`)
- .toContain(expectedHeader.objID);
-
- expect(typeEl.textContent).toBeTruthy();
- expect(typeEl.textContent)
- .withContext(`should contain ${expectedHeader.type}`)
- .toContain(expectedHeader.type);
-
- expect(imgEl.src).toBeTruthy();
- expect(imgEl.src).withContext(`should be ${expectedHeader.icon}`).toContain(expectedHeader.icon);
-
- expect(lastModEl.textContent).toBeTruthy();
- expect(lastModEl.textContent)
- .withContext(`should contain '${expectedHeader.lastmod}'`)
- .toContain(expectedHeader.lastmod);
+ expectToBe(tdEl.textContent, expectedHeader.objID);
+ expectToBe(typeEl.textContent, expectedHeader.type);
+ expectToContain(imgEl.src, expectedHeader.icon);
+ expectToBe(lastModEl.textContent, expectedHeader.lastmod);
});
it('... should render resourceUrl in div.resource-link', () => {
const rLinkDe = getAndExpectDebugElementByCss(compDe, 'div.resource-link', 1, 1);
const rLinkEl = rLinkDe[0].nativeElement;
- expect(rLinkEl.textContent).toBeTruthy();
- expect(rLinkEl.textContent)
- .withContext(`should contain ' API-Request: ${expectedResourceUrl}'`)
- .toContain(' API-Request: ' + expectedResourceUrl);
+ expectToBe(rLinkEl.textContent, ' API-Request: ' + expectedResourceUrl);
});
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/imageobjects/imageobjects.component.spec.ts b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/imageobjects/imageobjects.component.spec.ts
index a36fedf8e..25e58ed63 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/imageobjects/imageobjects.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/imageobjects/imageobjects.component.spec.ts
@@ -5,7 +5,12 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgxGalleryComponent, NgxGalleryImage, NgxGalleryModule, NgxGalleryOptions } from '@kolkov/ngx-gallery';
import { JsonConvert } from 'json2typescript';
-import { getAndExpectDebugElementByCss, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import {
+ expectToBe,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+ getAndExpectDebugElementByDirective,
+} from '@testing/expect-helper';
import { mockContextJson } from '@testing/mock-data';
import { ContextJson } from '@awg-shared/api-objects';
@@ -82,10 +87,7 @@ describe('ResourceDetailHtmlContentImageobjectsComponent', () => {
});
it('... should have galleryOptions', () => {
- expect(component.galleryOptions).toBeDefined();
- expect(component.galleryOptions)
- .withContext(`should equal expectedGalleryOptions: ${expectedGalleryOptions}`)
- .toEqual(jasmine.arrayContaining(expectedGalleryOptions));
+ expectToEqual(component.galleryOptions, jasmine.arrayContaining(expectedGalleryOptions));
});
describe('VIEW', () => {
@@ -105,8 +107,7 @@ describe('ResourceDetailHtmlContentImageobjectsComponent', () => {
});
it('... should have `images` inputs', () => {
- expect(component.images).toBeDefined();
- expect(component.images).withContext(`should be expectedImages: ${expectedImages}`).toBe(expectedImages);
+ expectToEqual(component.images, expectedImages);
});
describe('VIEW', () => {
@@ -115,17 +116,12 @@ describe('ResourceDetailHtmlContentImageobjectsComponent', () => {
});
it('... should contain one header showing number of images', () => {
- // Header debug element
const headerDes = getAndExpectDebugElementByCss(compDe, 'div.awg-image-obj > h5', 1, 1);
- // Size debug element
+
const sizeDes = getAndExpectDebugElementByCss(headerDes[0], 'span#awg-image-number', 1, 1);
const sizeEl = sizeDes[0].nativeElement;
- // Check size output
- expect(sizeEl.textContent).toBeDefined();
- expect(sizeEl.textContent)
- .withContext(`should be ${expectedImages.length.toString()}`)
- .toBe(expectedImages.length.toString());
+ expectToBe(sizeEl.textContent, expectedImages.length.toString());
});
it('... should contain one div.awg-image-slider with one NgxGalleryComponent', () => {
@@ -144,15 +140,8 @@ describe('ResourceDetailHtmlContentImageobjectsComponent', () => {
const galleryDes = getAndExpectDebugElementByDirective(compDe, NgxGalleryComponent, 1, 1);
const galleryCmp = galleryDes[0].injector.get(NgxGalleryComponent) as NgxGalleryComponent;
- expect(galleryCmp.options).toBeDefined();
- expect(galleryCmp.options)
- .withContext(`should equal expectedGalleryOptions: ${expectedGalleryOptions}`)
- .toEqual(expectedGalleryOptions);
-
- expect(galleryCmp.images).toBeDefined();
- expect(galleryCmp.images)
- .withContext(`should equal expectedGalleryImages: ${expectedImages}`)
- .toEqual(expectedImages);
+ expectToEqual(galleryCmp.options, expectedGalleryOptions);
+ expectToEqual(galleryCmp.images, expectedImages);
});
});
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/props/props.component.spec.ts b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/props/props.component.spec.ts
index d1240183d..291b92a70 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/props/props.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/props/props.component.spec.ts
@@ -1,5 +1,5 @@
import { DebugElement, SimpleChange } from '@angular/core';
-import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
+import { ComponentFixture, TestBed, fakeAsync, waitForAsync } from '@angular/core/testing';
import Spy = jasmine.Spy;
@@ -7,6 +7,9 @@ import { clickAndAwaitChanges } from '@testing/click-helper';
import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
import {
expectSpyCall,
+ expectToBe,
+ expectToContain,
+ expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -81,10 +84,7 @@ describe('ResourceDetailHtmlContentPropsComponent (DONE)', () => {
describe('BEFORE initial data binding', () => {
it('... should have `metaBreakLine`', () => {
- expect(component.metaBreakLine).withContext('should be defined').toBeDefined();
- expect(component.metaBreakLine)
- .withContext(`should be ${expectedMetaBreakLine}`)
- .toBe(expectedMetaBreakLine);
+ expectToBe(component.metaBreakLine, expectedMetaBreakLine);
});
it('... should not have `props` input', () => {
@@ -124,8 +124,7 @@ describe('ResourceDetailHtmlContentPropsComponent (DONE)', () => {
const headerEl = headerDes[0].nativeElement;
// Check output
- expect(headerEl.textContent).toBeTruthy();
- expect(headerEl.textContent).withContext('Objektdaten').toContain('Objektdaten');
+ expectToContain(headerEl.textContent, 'Objektdaten');
});
it('... should contain no ul with props yet', () => {
@@ -144,8 +143,7 @@ describe('ResourceDetailHtmlContentPropsComponent (DONE)', () => {
});
it('... should have `props` input', () => {
- expect(component.props).withContext('should be defined').toBeDefined();
- expect(component.props).withContext(`should be expectedProps: ${expectedProps}`).toBe(expectedProps);
+ expectToEqual(component.props, expectedProps);
});
describe('VIEW', () => {
@@ -183,16 +181,11 @@ describe('ResourceDetailHtmlContentPropsComponent (DONE)', () => {
const htmlDes = getAndExpectDebugElementByDirective(compDe, CompileHtmlComponent, 6, 6);
htmlDes.forEach(html => {
- expect(html.name).toBeTruthy();
- expect(html.name).withContext(`should be span`).toBe('span');
+ expectToBe(html.name, 'span');
// Check parent
- expect(html.parent.name).toBeTruthy();
- expect(html.parent.name).withContext(`should be li`).toBe('li');
- expect(html.parent.attributes['class']).toBeTruthy();
- expect(html.parent.attributes['class'])
- .withContext(`should be awg-prop-value`)
- .toBe('awg-prop-value');
+ expectToBe(html.parent.name, 'li');
+ expectToBe(html.parent.attributes['class'], 'awg-prop-value');
});
});
});
@@ -220,7 +213,7 @@ describe('ResourceDetailHtmlContentPropsComponent (DONE)', () => {
});
expectSpyCall(exposeGndSpy, 1, gndRemoveEvent);
- expect(exposeGndSpy.calls.mostRecent().args[0]).toEqual(gndRemoveEvent);
+ expectToEqual(exposeGndSpy.calls.mostRecent().args[0], gndRemoveEvent);
}));
it('... a REMOVE and SET event if props input contains a GND property', fakeAsync(() => {
@@ -234,8 +227,8 @@ describe('ResourceDetailHtmlContentPropsComponent (DONE)', () => {
// Gets triggered 2x (remove all old GND values & set new GND value)
expectSpyCall(exposeGndSpy, 2, gndSetEvent);
- expect(exposeGndSpy.calls.first().args[0]).toEqual(gndRemoveEvent);
- expect(exposeGndSpy.calls.mostRecent().args[0]).toEqual(gndSetEvent);
+ expectToEqual(exposeGndSpy.calls.first().args[0], gndRemoveEvent);
+ expectToEqual(exposeGndSpy.calls.mostRecent().args[0], gndSetEvent);
}));
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/resource-detail-html-content.component.spec.ts b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/resource-detail-html-content.component.spec.ts
index 2b90b17a7..754291b11 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/resource-detail-html-content.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html-content/resource-detail-html-content.component.spec.ts
@@ -1,5 +1,5 @@
import { Component, DebugElement, EventEmitter, Input, Output } from '@angular/core';
-import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
+import { ComponentFixture, TestBed, fakeAsync, waitForAsync } from '@angular/core/testing';
import Spy = jasmine.Spy;
import { NgxGalleryImage } from '@kolkov/ngx-gallery';
@@ -7,6 +7,7 @@ import { JsonConvert } from 'json2typescript';
import {
expectSpyCall,
+ expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -174,10 +175,7 @@ describe('ResourceDetailHtmlContentComponent (DONE)', () => {
});
it('... should have `content` inputs', () => {
- expect(component.content).withContext('should be defined').toBeDefined();
- expect(component.content)
- .withContext(`should be expectedIncoming: ${expectedContent}`)
- .toBe(expectedContent);
+ expectToEqual(component.content, expectedContent);
});
describe('VIEW', () => {
@@ -193,8 +191,7 @@ describe('ResourceDetailHtmlContentComponent (DONE)', () => {
ResourceDetailHtmlContentPropsStubComponent
) as ResourceDetailHtmlContentPropsStubComponent;
- expect(propsCmp.props).withContext('should be defined').toBeDefined();
- expect(propsCmp.props).withContext(`should be ${expectedContent.props}`).toBe(expectedContent.props);
+ expectToEqual(propsCmp.props, expectedContent.props);
});
it('... should pass down `content.images` to ResourceDetailHtmlContentImageobjectsComponent', () => {
@@ -209,10 +206,7 @@ describe('ResourceDetailHtmlContentComponent (DONE)', () => {
ResourceDetailHtmlContentImageobjectsStubComponent
) as ResourceDetailHtmlContentImageobjectsStubComponent;
- expect(imagesCmp.images).withContext('should be defined').toBeDefined();
- expect(imagesCmp.images)
- .withContext(`should be ${expectedContent.images}`)
- .toBe(expectedContent.images);
+ expectToEqual(imagesCmp.images, expectedContent.images);
});
it('... should pass down `content.incoming` to ResourceDetailHtmlContentLinkedobjectsComponent', () => {
@@ -227,10 +221,7 @@ describe('ResourceDetailHtmlContentComponent (DONE)', () => {
ResourceDetailHtmlContentLinkedobjectsStubComponent
) as ResourceDetailHtmlContentLinkedobjectsStubComponent;
- expect(incomingCmp.incomingGroups).withContext('should be defined').toBeDefined();
- expect(incomingCmp.incomingGroups)
- .withContext(`should be ${expectedContent.incoming}`)
- .toBe(expectedContent.incoming);
+ expectToEqual(incomingCmp.incomingGroups, expectedContent.incoming);
});
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html.component.spec.ts b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html.component.spec.ts
index 851a88bc5..6028f9882 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-html/resource-detail-html.component.spec.ts
@@ -1,11 +1,11 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Component, DebugElement, EventEmitter, Input, Output } from '@angular/core';
-import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
+import { ComponentFixture, TestBed, fakeAsync, waitForAsync } from '@angular/core/testing';
import Spy = jasmine.Spy;
import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
-import { expectSpyCall, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { GndEvent, GndEventType } from '@awg-core/services/gnd-service';
import {
@@ -121,10 +121,7 @@ describe('ResourceDetailHtmlComponent (DONE)', () => {
});
it('... should have `resourceDetailData` inputs', () => {
- expect(component.resourceDetailData).withContext('should be defined').toBeDefined();
- expect(component.resourceDetailData)
- .withContext(`should be ${expectedResourceDetailData}`)
- .toBe(expectedResourceDetailData);
+ expectToEqual(component.resourceDetailData, expectedResourceDetailData);
});
describe('VIEW', () => {
@@ -154,10 +151,7 @@ describe('ResourceDetailHtmlComponent (DONE)', () => {
ResourceDetailHtmlContentStubComponent
) as ResourceDetailHtmlContentStubComponent;
- expect(htmlContentCmp.content).toBeDefined();
- expect(htmlContentCmp.content)
- .withContext(`should be ${expectedResourceDetailData.content}`)
- .toBe(expectedResourceDetailData.content);
+ expectToBe(htmlContentCmp.content, expectedResourceDetailData.content);
});
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-converted/resource-detail-json-converted.component.spec.ts b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-converted/resource-detail-json-converted.component.spec.ts
index 44567af34..4125a8081 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-converted/resource-detail-json-converted.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-converted/resource-detail-json-converted.component.spec.ts
@@ -1,7 +1,7 @@
import { Component, DebugElement, Input } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-import { getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import { expectToBe, expectToEqual, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { ResourceFullResponseJson } from '@awg-shared/api-objects';
import { ResourceDetail, ResourceDetailContent } from '@awg-views/data-view/models';
@@ -62,10 +62,7 @@ describe('ResourceDetailJsonConvertedComponent (DONE)', () => {
const viewerDes = getAndExpectDebugElementByDirective(compDe, JsonViewerStubComponent, 1, 1);
const viewerCmp = viewerDes[0].injector.get(JsonViewerStubComponent) as JsonViewerStubComponent;
- expect(viewerCmp.jsonViewerHeader).toBeDefined();
- expect(viewerCmp.jsonViewerHeader)
- .withContext(`should have header: ${expectedHeader}`)
- .toBe(expectedHeader);
+ expectToBe(viewerCmp.jsonViewerHeader, expectedHeader);
});
it('... should not pass down `resourceJsonConvertedData` to json viewer component', () => {
@@ -87,10 +84,7 @@ describe('ResourceDetailJsonConvertedComponent (DONE)', () => {
});
it('... should have `resourceJsonConvertedData`', () => {
- expect(component.resourceJsonConvertedData).toBeDefined();
- expect(component.resourceJsonConvertedData)
- .withContext(`should equal ${expectedData}`)
- .toEqual(expectedData);
+ expectToEqual(component.resourceJsonConvertedData, expectedData);
});
describe('VIEW', () => {
@@ -98,8 +92,7 @@ describe('ResourceDetailJsonConvertedComponent (DONE)', () => {
const viewerDes = getAndExpectDebugElementByDirective(compDe, JsonViewerStubComponent, 1, 1);
const viewerCmp = viewerDes[0].injector.get(JsonViewerStubComponent) as JsonViewerStubComponent;
- expect(viewerCmp.jsonViewerData).toBeDefined();
- expect(viewerCmp.jsonViewerData).withContext(`should equal ${expectedData}`).toEqual(expectedData);
+ expectToEqual(viewerCmp.jsonViewerData, expectedData);
});
});
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-raw/resource-detail-json-raw.component.spec.ts b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-raw/resource-detail-json-raw.component.spec.ts
index 0bb33bd2d..db006d5c9 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-raw/resource-detail-json-raw.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail-json-raw/resource-detail-json-raw.component.spec.ts
@@ -1,7 +1,7 @@
import { Component, DebugElement, Input } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-import { getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import { expectToBe, expectToEqual, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { ResourceFullResponseJson } from '@awg-shared/api-objects';
import { ResourceDetail } from '@awg-views/data-view/models';
@@ -59,10 +59,7 @@ describe('ResourceDetailJsonRawComponent (DONE)', () => {
const viewerDes = getAndExpectDebugElementByDirective(compDe, JsonViewerStubComponent, 1, 1);
const viewerCmp = viewerDes[0].injector.get(JsonViewerStubComponent) as JsonViewerStubComponent;
- expect(viewerCmp.jsonViewerHeader).toBeDefined();
- expect(viewerCmp.jsonViewerHeader)
- .withContext(`should have header: ${expectedHeader}`)
- .toBe(expectedHeader);
+ expectToBe(viewerCmp.jsonViewerHeader, expectedHeader);
});
it('... should not pass down `resourceJsonRawData` to json viewer component', () => {
@@ -84,8 +81,7 @@ describe('ResourceDetailJsonRawComponent (DONE)', () => {
});
it('... should have `resourceJsonRawData`', () => {
- expect(component.resourceJsonRawData).toBeDefined();
- expect(component.resourceJsonRawData).withContext(`should equal ${expectedData}`).toEqual(expectedData);
+ expectToEqual(component.resourceJsonRawData, expectedData);
});
describe('VIEW', () => {
@@ -93,8 +89,7 @@ describe('ResourceDetailJsonRawComponent (DONE)', () => {
const viewerDes = getAndExpectDebugElementByDirective(compDe, JsonViewerStubComponent, 1, 1);
const viewerCmp = viewerDes[0].injector.get(JsonViewerStubComponent) as JsonViewerStubComponent;
- expect(viewerCmp.jsonViewerData).toBeDefined();
- expect(viewerCmp.jsonViewerData).withContext(`should have data: ${expectedData}`).toBe(expectedData);
+ expectToEqual(viewerCmp.jsonViewerData, expectedData);
});
});
});
diff --git a/src/app/views/data-view/data-outlets/resource-detail/resource-detail.component.html b/src/app/views/data-view/data-outlets/resource-detail/resource-detail.component.html
index 6019cdbeb..ff441e429 100644
--- a/src/app/views/data-view/data-outlets/resource-detail/resource-detail.component.html
+++ b/src/app/views/data-view/data-outlets/resource-detail/resource-detail.component.html
@@ -8,7 +8,7 @@
} @else {
@if (errorMessage) {
-
+
Die Anfrage "{{ errorMessage?.route }}" ist fehlgeschlagen.
Fehlermeldung: "{{ errorMessage?.statusText || errorMessage }}".
Möglicherweise gab es ein Problem mit der Internetverbindung oder dem verwendeten Suchbegriff.
diff --git a/src/app/views/data-view/data-outlets/search-overview.component.spec.ts b/src/app/views/data-view/data-outlets/search-overview.component.spec.ts
index 9d6d6758a..62edd6d8b 100644
--- a/src/app/views/data-view/data-outlets/search-overview.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/search-overview.component.spec.ts
@@ -6,7 +6,7 @@ import { ActivatedRoute, QueryParamsHandling } from '@angular/router';
import Spy = jasmine.Spy;
-import { expectSpyCall, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { ActivatedRouteStub, RouterOutletStubComponent, UrlSegmentStub } from '@testing/router-stubs';
import { SideInfoService } from '@awg-core/services';
@@ -96,18 +96,14 @@ describe('SearchOverviewComponent (DONE)', () => {
});
it('... should change urls', () => {
- expect(mockActivatedRoute.snapshot.url[0].path).toBeTruthy();
- expect(mockActivatedRoute.snapshot.url[0].path)
- .withContext(`should equal ${expectedPath}`)
- .toEqual(expectedPath);
+ expectToBe(mockActivatedRoute.snapshot.url[0].path, expectedPath);
const changedPath = 'other';
const changedRouteUrl: UrlSegmentStub[] = [{ path: changedPath }];
mockActivatedRoute.testUrl = changedRouteUrl;
- expect(mockActivatedRoute.snapshot.url[0].path).toBeTruthy();
- expect(mockActivatedRoute.snapshot.url[0].path).withContext(`should equal ${changedPath}`).toEqual(changedPath);
+ expectToBe(mockActivatedRoute.snapshot.url[0].path, changedPath);
});
describe('BEFORE initial data binding', () => {
@@ -185,10 +181,7 @@ describe('SearchOverviewComponent (DONE)', () => {
RouterLinkButtonGroupStubComponent
) as RouterLinkButtonGroupStubComponent;
- expect(buttonCmp.routerLinkButtons).toBeTruthy();
- expect(buttonCmp.routerLinkButtons)
- .withContext(`should equal ${expectedSearchRouterLinkButtons}`)
- .toEqual(expectedSearchRouterLinkButtons);
+ expectToEqual(buttonCmp.routerLinkButtons, expectedSearchRouterLinkButtons);
});
});
@@ -198,10 +191,7 @@ describe('SearchOverviewComponent (DONE)', () => {
});
it('... should have `searchRouterLinkButtons`', () => {
- expect(component.searchRouterLinkButtons).withContext('should be defined').toBeDefined();
- expect(component.searchRouterLinkButtons)
- .withContext(`should equal ${expectedSearchRouterLinkButtons}`)
- .toEqual(expectedSearchRouterLinkButtons);
+ expectToEqual(component.searchRouterLinkButtons, expectedSearchRouterLinkButtons);
});
});
diff --git a/src/app/views/data-view/data-outlets/search-panel/extended-search-form/extended-search-form.component.spec.ts b/src/app/views/data-view/data-outlets/search-panel/extended-search-form/extended-search-form.component.spec.ts
index 29e269426..7c3210f5d 100644
--- a/src/app/views/data-view/data-outlets/search-panel/extended-search-form/extended-search-form.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/search-panel/extended-search-form/extended-search-form.component.spec.ts
@@ -14,19 +14,25 @@ import { faPlus, faRefresh, faSearch, faTrash } from '@fortawesome/free-solid-sv
import { click, clickAndAwaitChanges } from '@testing/click-helper';
import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
-import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import {
+ expectSpyCall,
+ expectToBe,
+ expectToContain,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+} from '@testing/expect-helper';
import {
mockPropertyTypesInResourceClassResponseJson,
mockResourceTypesInVocabularyResponseJson,
} from '@testing/mock-data';
import { mockConsole } from '@testing/mock-helper';
-import { ExtendedSearchParams, SearchCompop, SearchCompopSetsList } from '@awg-app/views/data-view/models';
import {
PropertyTypesInResourceClassResponseJson,
ResourceTypesInVocabularyResponseJson,
} from '@awg-shared/api-objects';
import { SEARCH_COMPOP_SETS_LIST } from '@awg-views/data-view/data';
+import { ExtendedSearchParams, SearchCompop, SearchCompopSetsList } from '@awg-views/data-view/models';
import { DataApiService } from '@awg-views/data-view/services';
import { ExtendedSearchFormComponent } from './extended-search-form.component';
@@ -380,7 +386,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const labelEl = labelDes[0].nativeElement;
- expect(labelEl.classList).toContain('text-muted');
+ expectToContain(labelEl.classList, 'text-muted');
expectToBe(labelEl.textContent, 'Resource type');
});
});
@@ -509,7 +515,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const labelEl = labelDes[0].nativeElement;
- expect(labelEl.classList).toContain('text-muted');
+ expectToContain(labelEl.classList, 'text-muted');
expectToBe(labelEl.textContent, 'Property');
});
});
@@ -628,7 +634,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const labelEl = labelDes[0].nativeElement;
- expect(labelEl.classList).toContain('text-muted');
+ expectToContain(labelEl.classList, 'text-muted');
expectToBe(labelEl.textContent, 'Operator');
});
});
@@ -688,7 +694,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const labelEl = labelDes[0].nativeElement;
- expect(labelEl.classList).toContain('text-muted');
+ expectToContain(labelEl.classList, 'text-muted');
expectToBe(labelEl.textContent, 'Search value');
});
});
@@ -746,7 +752,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const buttonEl = buttonDes[0].nativeElement;
- expect(buttonEl.classList).toContain('btn-outline-info');
+ expectToContain(buttonEl.classList, 'btn-outline-info');
});
});
@@ -916,7 +922,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const buttonEl = buttonDes[0].nativeElement;
- expect(buttonEl.classList).toContain('btn-outline-danger');
+ expectToContain(buttonEl.classList, 'btn-outline-danger');
});
});
@@ -985,7 +991,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const buttonEl = buttonDes[0].nativeElement;
- expect(buttonEl.classList).toContain('btn-outline-info');
+ expectToContain(buttonEl.classList, 'btn-outline-info');
});
it('... should have the search button disabled as long as the form is not valid', () => {
@@ -1067,7 +1073,7 @@ describe('ExtendedSearchFormComponent', () => {
);
const buttonEl = buttonDes[0].nativeElement;
- expect(buttonEl.classList).toContain('btn-outline-danger');
+ expectToContain(buttonEl.classList, 'btn-outline-danger');
});
it('... should have the reset button disabled as long as the restypeControl is not valid', () => {
@@ -1415,7 +1421,7 @@ describe('ExtendedSearchFormComponent', () => {
});
it('... should return null if the index is out of bounds', () => {
- expect(component.getCompopControlAtIndex(100)).toBeNull();
+ expectToBe(component.getCompopControlAtIndex(100), null);
});
});
@@ -1436,12 +1442,12 @@ describe('ExtendedSearchFormComponent', () => {
for (const guieElementId of ['3', '6', '14']) {
const compopSet = component.getCompopSetByValueType(valueTypeId, guieElementId);
- expect(typeof compopSet).toBe('object');
- expect(Array.isArray(compopSet)).toBeTrue();
+ expectToBe(typeof compopSet, 'object');
+ expectToBe(Array.isArray(compopSet), true);
expect(compopSet.length).toBeGreaterThanOrEqual(0);
compopSet.forEach(compop => {
- expect(compop instanceof SearchCompop).toBeTrue();
+ expectToBe(compop instanceof SearchCompop, true);
});
}
}
@@ -1599,7 +1605,7 @@ describe('ExtendedSearchFormComponent', () => {
});
it('... should return null if the propertyIdControl does not exist', () => {
- expect(component.getPropertyIdControlAtIndex(100)).toBeNull();
+ expectToBe(component.getPropertyIdControlAtIndex(100), null);
});
});
@@ -2765,13 +2771,13 @@ describe('ExtendedSearchFormComponent', () => {
it('... the index is out of bounds', () => {
const index = 100;
- expect((component as any)._getFormArrayControlAtIndex('searchvalControl', index)).toBeNull();
+ expectToBe((component as any)._getFormArrayControlAtIndex('searchvalControl', index), null);
});
it('... the control does not exist', () => {
const index = 0;
- expect((component as any)._getFormArrayControlAtIndex('invalidControl', index)).toBeNull();
+ expectToBe((component as any)._getFormArrayControlAtIndex('invalidControl', index), null);
});
});
@@ -2815,7 +2821,7 @@ describe('ExtendedSearchFormComponent', () => {
'compopControl'
].setValue('EXISTS');
- expect((component as any)._isCompopExists(index)).toBeTrue();
+ expectToBe((component as any)._isCompopExists(index), true);
});
it('... should return false if the compop value is not `EXISTS`', () => {
@@ -2825,7 +2831,7 @@ describe('ExtendedSearchFormComponent', () => {
'compopControl'
].setValue('EQUALS');
- expect((component as any)._isCompopExists(index)).toBeFalse();
+ expectToBe((component as any)._isCompopExists(index), false);
});
});
@@ -2839,7 +2845,7 @@ describe('ExtendedSearchFormComponent', () => {
isFormControlValueMissingSpy.withArgs('compopControl', index).and.returnValue(true);
- expect((component as any)._isCompopMissing(index)).toBeTrue();
+ expectToBe((component as any)._isCompopMissing(index), true);
});
it('... should return false if `_isFormControlValueMissing` returns false', () => {
@@ -2847,7 +2853,7 @@ describe('ExtendedSearchFormComponent', () => {
isFormControlValueMissingSpy.withArgs('compopControl', index).and.returnValue(false);
- expect((component as any)._isCompopMissing(index)).toBeFalse();
+ expectToBe((component as any)._isCompopMissing(index), false);
});
});
@@ -2865,7 +2871,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue(null);
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeTrue();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), true);
});
it('... undefined', () => {
@@ -2876,7 +2882,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue(undefined);
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeTrue();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), true);
});
it('... an empty string', () => {
@@ -2887,7 +2893,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue('');
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeTrue();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), true);
});
it('... the default formString', () => {
@@ -2898,7 +2904,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue(expectedDefaultFormString);
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeTrue();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), true);
});
});
@@ -2910,7 +2916,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue(1);
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeFalse();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), false);
});
it('... a string', () => {
@@ -2920,7 +2926,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue('test');
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeFalse();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), false);
});
it('... an object', () => {
@@ -2930,7 +2936,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue({ id: 1 });
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeFalse();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), false);
});
it('... an empty object', () => {
@@ -2940,7 +2946,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue({});
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeFalse();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), false);
});
it('... an empty array', () => {
@@ -2950,7 +2956,7 @@ describe('ExtendedSearchFormComponent', () => {
'searchvalControl'
].setValue([]);
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeFalse();
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), false);
});
});
@@ -2964,9 +2970,9 @@ describe('ExtendedSearchFormComponent', () => {
controls['compopControl'].setValue('EXISTS');
controls['searchvalControl'].setValue(null);
- expect((component as any)._isFormControlValueMissing('propertyIdControl', index)).toBeFalse();
- expect((component as any)._isFormControlValueMissing('compopControl', index)).toBeFalse();
- expect((component as any)._isFormControlValueMissing('searchvalControl', index)).toBeTrue();
+ expectToBe((component as any)._isFormControlValueMissing('propertyIdControl', index), false);
+ expectToBe((component as any)._isFormControlValueMissing('compopControl', index), false);
+ expectToBe((component as any)._isFormControlValueMissing('searchvalControl', index), true);
});
});
@@ -2983,8 +2989,8 @@ describe('ExtendedSearchFormComponent', () => {
component.addPropertiesControl();
component.addPropertiesControl();
- expect((component as any)._isNotLastProperty(index)).toBeTrue();
- expect((component as any)._isNotLastProperty(index1)).toBeTrue();
+ expectToBe((component as any)._isNotLastProperty(index), true);
+ expectToBe((component as any)._isNotLastProperty(index1), true);
});
it('... less than the length - 1 of the propertiesControls', () => {
@@ -2993,7 +2999,7 @@ describe('ExtendedSearchFormComponent', () => {
component.addPropertiesControl();
component.addPropertiesControl();
- expect((component as any)._isNotLastProperty(index)).toBeTrue();
+ expectToBe((component as any)._isNotLastProperty(index), true);
});
it('... negative', () => {
@@ -3002,7 +3008,7 @@ describe('ExtendedSearchFormComponent', () => {
component.addPropertiesControl();
component.addPropertiesControl();
- expect((component as any)._isNotLastProperty(index)).toBeTrue();
+ expectToBe((component as any)._isNotLastProperty(index), true);
});
});
@@ -3010,7 +3016,7 @@ describe('ExtendedSearchFormComponent', () => {
it('... the last index position in the propertiesControls', () => {
const index = 0;
- expect((component as any)._isNotLastProperty(index)).toBeFalse();
+ expectToBe((component as any)._isNotLastProperty(index), false);
// Add tow more properties controls
component.addPropertiesControl();
@@ -3018,7 +3024,7 @@ describe('ExtendedSearchFormComponent', () => {
const index2 = 2;
- expect((component as any)._isNotLastProperty(index2)).toBeFalse();
+ expectToBe((component as any)._isNotLastProperty(index2), false);
});
it('... greater than the length - 1 of the propertiesControls', () => {
@@ -3027,7 +3033,7 @@ describe('ExtendedSearchFormComponent', () => {
component.addPropertiesControl();
component.addPropertiesControl();
- expect((component as any)._isNotLastProperty(index)).toBeFalse();
+ expectToBe((component as any)._isNotLastProperty(index), false);
});
it('... equal to the length - 1 of the propertiesControls', () => {
@@ -3036,7 +3042,7 @@ describe('ExtendedSearchFormComponent', () => {
component.addPropertiesControl();
component.addPropertiesControl();
- expect((component as any)._isNotLastProperty(index)).toBeFalse();
+ expectToBe((component as any)._isNotLastProperty(index), false);
});
});
});
@@ -3051,7 +3057,7 @@ describe('ExtendedSearchFormComponent', () => {
isFormControlValueMissingSpy.withArgs('propertyIdControl', index).and.returnValue(true);
- expect((component as any)._isPropertyIdMissing(index)).toBeTrue();
+ expectToBe((component as any)._isPropertyIdMissing(index), true);
});
it('... should return false if `_isFormControlValueMissing` returns false', () => {
@@ -3059,7 +3065,7 @@ describe('ExtendedSearchFormComponent', () => {
isFormControlValueMissingSpy.withArgs('propertyIdControl', index).and.returnValue(false);
- expect((component as any)._isPropertyIdMissing(index)).toBeFalse();
+ expectToBe((component as any)._isPropertyIdMissing(index), false);
});
});
@@ -3075,7 +3081,7 @@ describe('ExtendedSearchFormComponent', () => {
isPropertyIdMissingSpy.withArgs(index).and.returnValue(true);
isCompopMissingSpy.withArgs(index).and.returnValue(false);
- expect((component as any)._isPropertyIdOrCompopMissing(index)).toBeTrue();
+ expectToBe((component as any)._isPropertyIdOrCompopMissing(index), true);
});
it('... `_isCompopMissing` returns true', () => {
@@ -3084,7 +3090,7 @@ describe('ExtendedSearchFormComponent', () => {
isPropertyIdMissingSpy.withArgs(index).and.returnValue(false);
isCompopMissingSpy.withArgs(index).and.returnValue(true);
- expect((component as any)._isPropertyIdOrCompopMissing(index)).toBeTrue();
+ expectToBe((component as any)._isPropertyIdOrCompopMissing(index), true);
});
it('... `_isPropertyIdMissing` and `_isCompopMissing` both return true', () => {
@@ -3093,7 +3099,7 @@ describe('ExtendedSearchFormComponent', () => {
isPropertyIdMissingSpy.withArgs(index).and.returnValue(true);
isCompopMissingSpy.withArgs(index).and.returnValue(true);
- expect((component as any)._isPropertyIdOrCompopMissing(index)).toBeTrue();
+ expectToBe((component as any)._isPropertyIdOrCompopMissing(index), true);
});
});
@@ -3103,7 +3109,7 @@ describe('ExtendedSearchFormComponent', () => {
isPropertyIdMissingSpy.withArgs(index).and.returnValue(false);
isCompopMissingSpy.withArgs(index).and.returnValue(false);
- expect((component as any)._isPropertyIdOrCompopMissing(index)).toBeFalse();
+ expectToBe((component as any)._isPropertyIdOrCompopMissing(index), false);
});
});
@@ -3116,25 +3122,25 @@ describe('ExtendedSearchFormComponent', () => {
it('... an empty string', () => {
component.extendedSearchForm.controls['restypeControl'].setValue('');
- expect((component as any)._isResourecetypeMissing()).toBeTrue();
+ expectToBe((component as any)._isResourecetypeMissing(), true);
});
it('... undefined', () => {
component.extendedSearchForm.controls['restypeControl'].setValue(undefined);
- expect((component as any)._isResourecetypeMissing()).toBeTrue();
+ expectToBe((component as any)._isResourecetypeMissing(), true);
});
it('... null', () => {
component.extendedSearchForm.controls['restypeControl'].setValue(null);
- expect((component as any)._isResourecetypeMissing()).toBeTrue();
+ expectToBe((component as any)._isResourecetypeMissing(), true);
});
it('... the default formString', () => {
component.extendedSearchForm.controls['restypeControl'].setValue(expectedDefaultFormString);
- expect((component as any)._isResourecetypeMissing()).toBeTrue();
+ expectToBe((component as any)._isResourecetypeMissing(), true);
});
});
@@ -3142,31 +3148,31 @@ describe('ExtendedSearchFormComponent', () => {
it('... a number', () => {
component.extendedSearchForm.controls['restypeControl'].setValue(1);
- expect((component as any)._isResourecetypeMissing()).toBeFalse();
+ expectToBe((component as any)._isResourecetypeMissing(), false);
});
it('... a string', () => {
component.extendedSearchForm.controls['restypeControl'].setValue('1');
- expect((component as any)._isResourecetypeMissing()).toBeFalse();
+ expectToBe((component as any)._isResourecetypeMissing(), false);
});
it('... an object', () => {
component.extendedSearchForm.controls['restypeControl'].setValue({ id: 1 });
- expect((component as any)._isResourecetypeMissing()).toBeFalse();
+ expectToBe((component as any)._isResourecetypeMissing(), false);
});
it('... an empty object', () => {
component.extendedSearchForm.controls['restypeControl'].setValue({});
- expect((component as any)._isResourecetypeMissing()).toBeFalse();
+ expectToBe((component as any)._isResourecetypeMissing(), false);
});
it('... an empty array', () => {
component.extendedSearchForm.controls['restypeControl'].setValue([]);
- expect((component as any)._isResourecetypeMissing()).toBeFalse();
+ expectToBe((component as any)._isResourecetypeMissing(), false);
});
});
});
@@ -3181,7 +3187,7 @@ describe('ExtendedSearchFormComponent', () => {
isFormControlValueMissingSpy.withArgs('searchvalControl', index).and.returnValue(true);
- expect((component as any)._isSearchvalMissing(index)).toBeTrue();
+ expectToBe((component as any)._isSearchvalMissing(index), true);
});
it('... should return false if `_isFormControlValueMissing` returns false', () => {
@@ -3189,7 +3195,7 @@ describe('ExtendedSearchFormComponent', () => {
isFormControlValueMissingSpy.withArgs('searchvalControl', index).and.returnValue(false);
- expect((component as any)._isSearchvalMissing(index)).toBeFalse();
+ expectToBe((component as any)._isSearchvalMissing(index), false);
});
});
@@ -3205,7 +3211,7 @@ describe('ExtendedSearchFormComponent', () => {
isSearchvalMissingSpy.withArgs(index).and.returnValue(true);
isSearchvalTooShortSpy.withArgs(index).and.returnValue(false);
- expect((component as any)._isSearchvalMissingOrTooShort(index)).toBeTrue();
+ expectToBe((component as any)._isSearchvalMissingOrTooShort(index), true);
});
it('... `_isSearchvalTooShort` returns true', () => {
@@ -3214,7 +3220,7 @@ describe('ExtendedSearchFormComponent', () => {
isSearchvalMissingSpy.withArgs(index).and.returnValue(false);
isSearchvalTooShortSpy.withArgs(index).and.returnValue(true);
- expect((component as any)._isSearchvalMissingOrTooShort(index)).toBeTrue();
+ expectToBe((component as any)._isSearchvalMissingOrTooShort(index), true);
});
it('... `_isSearchvalMissing` and `_isSearchvalTooShort` both return true', () => {
@@ -3223,7 +3229,7 @@ describe('ExtendedSearchFormComponent', () => {
isSearchvalMissingSpy.withArgs(index).and.returnValue(true);
isSearchvalTooShortSpy.withArgs(index).and.returnValue(true);
- expect((component as any)._isSearchvalMissingOrTooShort(index)).toBeTrue();
+ expectToBe((component as any)._isSearchvalMissingOrTooShort(index), true);
});
});
@@ -3233,7 +3239,7 @@ describe('ExtendedSearchFormComponent', () => {
isSearchvalMissingSpy.withArgs(index).and.returnValue(false);
isSearchvalTooShortSpy.withArgs(index).and.returnValue(false);
- expect((component as any)._isSearchvalMissingOrTooShort(index)).toBeFalse();
+ expectToBe((component as any)._isSearchvalMissingOrTooShort(index), false);
});
});
@@ -3252,9 +3258,9 @@ describe('ExtendedSearchFormComponent', () => {
controls[1]['controls']['searchvalControl'].setValue('a');
controls[2]['controls']['searchvalControl'].setValue('ab');
- expect((component as any)._isSearchvalTooShort(0)).toBeTrue();
- expect((component as any)._isSearchvalTooShort(1)).toBeTrue();
- expect((component as any)._isSearchvalTooShort(2)).toBeTrue();
+ expectToBe((component as any)._isSearchvalTooShort(0), true);
+ expectToBe((component as any)._isSearchvalTooShort(1), true);
+ expectToBe((component as any)._isSearchvalTooShort(2), true);
});
it('... should return false if the searchval control at a given index has a value that is equal or longer than 3 characters', () => {
@@ -3267,9 +3273,9 @@ describe('ExtendedSearchFormComponent', () => {
controls[1]['controls']['searchvalControl'].setValue('abcd');
controls[2]['controls']['searchvalControl'].setValue('abcde');
- expect((component as any)._isSearchvalTooShort(0)).toBeFalse();
- expect((component as any)._isSearchvalTooShort(1)).toBeFalse();
- expect((component as any)._isSearchvalTooShort(2)).toBeFalse();
+ expectToBe((component as any)._isSearchvalTooShort(0), false);
+ expectToBe((component as any)._isSearchvalTooShort(1), false);
+ expectToBe((component as any)._isSearchvalTooShort(2), false);
});
});
@@ -3300,7 +3306,7 @@ describe('ExtendedSearchFormComponent', () => {
compopControl.setValue('EXISTS');
- expect(validator(searchvalControl)).toBeNull();
+ expectToBe(validator(searchvalControl), null);
});
it('... should require non-null searchvalControl when compopControl has value other than `EXISTS`', () => {
@@ -3349,7 +3355,7 @@ describe('ExtendedSearchFormComponent', () => {
searchvalControl.setValue('abc');
- expect(validator(searchvalControl)).toBeNull();
+ expectToBe(validator(searchvalControl), null);
});
});
});
diff --git a/src/app/views/data-view/data-outlets/search-panel/fulltext-search-form/fulltext-search-form.component.spec.ts b/src/app/views/data-view/data-outlets/search-panel/fulltext-search-form/fulltext-search-form.component.spec.ts
index 04191cce2..eeeb9e7e8 100644
--- a/src/app/views/data-view/data-outlets/search-panel/fulltext-search-form/fulltext-search-form.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/search-panel/fulltext-search-form/fulltext-search-form.component.spec.ts
@@ -6,7 +6,13 @@ import { FontAwesomeTestingModule } from '@fortawesome/angular-fontawesome/testi
import { faSearch, IconDefinition } from '@fortawesome/free-solid-svg-icons';
import Spy = jasmine.Spy;
-import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import {
+ expectSpyCall,
+ expectToBe,
+ expectToContain,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+} from '@testing/expect-helper';
import { FulltextSearchFormComponent } from './fulltext-search-form.component';
@@ -227,7 +233,7 @@ describe('FulltextSearchFormComponent (DONE)', () => {
const inputDe = getAndExpectDebugElementByCss(formFloatingGroupDe[0], 'input.form-control', 1, 1);
const inputEl = inputDe[0].nativeElement;
- expect(inputEl.classList).toContain('is-invalid');
+ expectToContain(inputEl.classList, 'is-invalid');
});
it('... should have class `ng-pristine`, but not `ng-dirty` in input.form-control', () => {
@@ -240,16 +246,16 @@ describe('FulltextSearchFormComponent (DONE)', () => {
const inputDe = getAndExpectDebugElementByCss(formFloatingGroupDe[0], 'input.form-control', 1, 1);
const inputEl = inputDe[0].nativeElement;
- expect(inputEl.classList).toContain('ng-pristine');
+ expectToContain(inputEl.classList, 'ng-pristine');
expect(inputEl.classList).not.toContain('ng-dirty');
});
it('... should have an invalid searchval input', () => {
- expect(component.searchvalControl.valid).toBeFalse();
+ expectToBe(component.searchvalControl.valid, false);
});
it('... should have an invalid form', () => {
- expect(component.fulltextSearchForm.valid).toBeFalse();
+ expectToBe(component.fulltextSearchForm.valid, false);
});
it('... should not have a div.invalid-feedback', () => {
@@ -303,7 +309,7 @@ describe('FulltextSearchFormComponent (DONE)', () => {
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(inputEl.classList).toContain('is-invalid');
+ expectToContain(inputEl.classList, 'is-invalid');
});
it('... should not have class `ng-pristine`, but `ng-dirty` in input.form-control', () => {
@@ -325,7 +331,7 @@ describe('FulltextSearchFormComponent (DONE)', () => {
fixture.detectChanges();
expect(inputEl.classList).not.toContain('ng-pristine');
- expect(inputEl.classList).toContain('ng-dirty');
+ expectToContain(inputEl.classList, 'ng-dirty');
});
it('... should have an invalid searchval input', () => {
@@ -334,7 +340,7 @@ describe('FulltextSearchFormComponent (DONE)', () => {
component.setSearchvalFromInput();
fixture.detectChanges();
- expect(component.searchvalControl.valid).toBeFalse();
+ expectToBe(component.searchvalControl.valid, false);
});
it('... should have an invalid form', () => {
@@ -343,7 +349,7 @@ describe('FulltextSearchFormComponent (DONE)', () => {
component.setSearchvalFromInput();
fixture.detectChanges();
- expect(component.fulltextSearchForm.valid).toBeFalse();
+ expectToBe(component.fulltextSearchForm.valid, false);
});
it('... should have a div.invalid-feedback if form is invalid after input', () => {
@@ -461,7 +467,7 @@ describe('FulltextSearchFormComponent (DONE)', () => {
fixture.detectChanges();
expect(inputEl.classList).not.toContain('ng-pristine');
- expect(inputEl.classList).toContain('ng-dirty');
+ expectToContain(inputEl.classList, 'ng-dirty');
}));
it('... should have a valid searchval input', () => {
diff --git a/src/app/views/data-view/data-outlets/search-panel/search-panel.component.html b/src/app/views/data-view/data-outlets/search-panel/search-panel.component.html
index 566e3d8d8..104374520 100644
--- a/src/app/views/data-view/data-outlets/search-panel/search-panel.component.html
+++ b/src/app/views/data-view/data-outlets/search-panel/search-panel.component.html
@@ -34,7 +34,7 @@
} @else {
@if (errorMessage) {
-
+
Die Anfrage "{{ errorMessage?.route }}" ist fehlgeschlagen.
Fehlermeldung: "{{ errorMessage?.statusText || errorMessage }}".
Möglicherweise gab es ein Problem mit der Internetverbindung oder der Suchanfrage.
diff --git a/src/app/views/data-view/data-outlets/search-panel/search-result-list/search-result-list.component.spec.ts b/src/app/views/data-view/data-outlets/search-panel/search-result-list/search-result-list.component.spec.ts
index 39e84f7f0..a7e4cf310 100644
--- a/src/app/views/data-view/data-outlets/search-panel/search-result-list/search-result-list.component.spec.ts
+++ b/src/app/views/data-view/data-outlets/search-panel/search-result-list/search-result-list.component.spec.ts
@@ -10,6 +10,8 @@ import Spy = jasmine.Spy;
import { FontAwesomeTestingModule } from '@fortawesome/angular-fontawesome/testing';
import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
+import { expectToBe } from '@testing/expect-helper';
+
import { ConversionService, DataStreamerService, SideInfoService } from '@awg-core/services';
import { SearchResponseJson } from '@awg-shared/api-objects';
import { CompileHtmlComponent } from '@awg-shared/compile-html';
@@ -105,14 +107,14 @@ describe('SearchResultListComponent', () => {
});
it('... injected conversion service should use provided mockValue', () => {
- expect(conversionService === mockConversionService).toBeTrue();
+ expectToBe(conversionService === mockConversionService, true);
});
it('... injected datastreamer service should use provided mockValue', () => {
- expect(dataStreamerService === mockDataStreamerService).toBeTrue();
+ expectToBe(dataStreamerService === mockDataStreamerService, true);
});
it('... injected sideinfo service should use provided mockValue', () => {
- expect(sideInfoService === mockSideInfoService).toBeTrue();
+ expectToBe(sideInfoService === mockSideInfoService, true);
});
});
diff --git a/src/app/views/data-view/data-view.component.spec.ts b/src/app/views/data-view/data-view.component.spec.ts
index fde023756..da94e5d7f 100644
--- a/src/app/views/data-view/data-view.component.spec.ts
+++ b/src/app/views/data-view/data-view.component.spec.ts
@@ -8,6 +8,7 @@ import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import {
expectSpyCall,
+ expectToBe,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -65,11 +66,8 @@ describe('DataViewComponent (DONE)', () => {
describe('BEFORE initial data binding', () => {
it('... should have title and id', () => {
- expect(component.searchTitle).toBeDefined();
- expect(component.searchTitle).withContext(`should be ${expectedTitle}`).toBe(expectedTitle);
-
- expect(component.searchId).toBeDefined();
- expect(component.searchId).withContext(`should be ${expectedId}`).toBe(expectedId);
+ expectToBe(component.searchTitle, expectedTitle);
+ expectToBe(component.searchId, expectedId);
});
describe('#routeToSidenav()', () => {
@@ -137,9 +135,7 @@ describe('DataViewComponent (DONE)', () => {
expect(navArgs).toBeDefined();
expect(navArgs[0]).toBeDefined();
- expect(outletRoute).toBeDefined();
- expect(outletRoute).withContext(`should be: ${expectedRoute}`).toBe(expectedRoute);
-
+ expectToBe(outletRoute, expectedRoute);
expect(navigationSpy).toHaveBeenCalledWith(navArgs[0], navArgs[1]);
});
@@ -149,8 +145,7 @@ describe('DataViewComponent (DONE)', () => {
const navExtras = navArgs[1];
expect(navExtras).toBeDefined();
- expect(navExtras.preserveFragment).toBeDefined();
- expect(navExtras.preserveFragment).withContext('should be `preserveFragment:true`').toBe(true);
+ expectToBe(navExtras.preserveFragment, true);
expect(navigationSpy).toHaveBeenCalledWith(navArgs[0], navArgs[1]);
});
@@ -161,11 +156,8 @@ describe('DataViewComponent (DONE)', () => {
const headingDes = getAndExpectDebugElementByDirective(compDe, HeadingStubComponent, 1, 1);
const headingCmp = headingDes[0].injector.get(HeadingStubComponent) as HeadingStubComponent;
- expect(headingCmp.title).toBeTruthy();
- expect(headingCmp.title).withContext(`should have title: ${expectedTitle}`).toBe(expectedTitle);
-
- expect(headingCmp.id).toBeTruthy();
- expect(headingCmp.id).withContext(`should have id: ${expectedId}`).toBe(expectedId);
+ expectToBe(headingCmp.title, expectedTitle);
+ expectToBe(headingCmp.id, expectedId);
});
});
});
diff --git a/src/app/views/data-view/services/bibliography.service.spec.ts b/src/app/views/data-view/services/bibliography.service.spec.ts
index 6f4dd22eb..114b8cc77 100644
--- a/src/app/views/data-view/services/bibliography.service.spec.ts
+++ b/src/app/views/data-view/services/bibliography.service.spec.ts
@@ -9,7 +9,7 @@ import Spy = jasmine.Spy;
import { JsonConvert } from 'json2typescript';
-import { expectSpyCall } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, expectToEqual } from '@testing/expect-helper';
import { mockResourceFullResponseJson, mockSearchResponseJson } from '@testing/mock-data';
import { AppConfig } from '@awg-app/app.config';
@@ -74,45 +74,28 @@ describe('BibliographyService (DONE)', () => {
it('... should have serviceName', () => {
const expectedServiceName = 'BibliographyService';
- expect(bibliographyService.serviceName).toBeDefined();
- expect(bibliographyService.serviceName)
- .withContext(`should be ${expectedServiceName}`)
- .toBe(expectedServiceName);
+ expectToBe(bibliographyService.serviceName, expectedServiceName);
});
it('... should have projectId', () => {
- expect(bibliographyService.projectId).toBeDefined();
- expect(bibliographyService.projectId).withContext(`should be ${expectedProjectId}`).toBe(expectedProjectId);
+ expectToBe(bibliographyService.projectId, expectedProjectId);
});
it('... should have resTypeId', () => {
- expect(bibliographyService.resTypeId).toBeDefined();
- expect(bibliographyService.resTypeId).withContext(`should be ${expectedResTypeId}`).toBe(expectedResTypeId);
+ expectToBe(bibliographyService.resTypeId, expectedResTypeId);
});
it('... should have bibShortTitlePropertyId', () => {
- expect(bibliographyService.bibShortTitlePropertyId).toBeDefined();
- expect(bibliographyService.bibShortTitlePropertyId)
- .withContext(`should be ${expectedBibShortTitlePropertyId}`)
- .toBe(expectedBibShortTitlePropertyId);
+ expectToBe(bibliographyService.bibShortTitlePropertyId, expectedBibShortTitlePropertyId);
});
it('... should have routes', () => {
- expect(bibliographyService.resourcesRoute).toBeDefined();
- expect(bibliographyService.resourcesRoute)
- .withContext(`should be ${expectedResourcesRoute}`)
- .toBe(expectedResourcesRoute);
-
- expect(bibliographyService.searchRoute).toBeDefined();
- expect(bibliographyService.searchRoute)
- .withContext(`should be ${expectedSearchRoute}`)
- .toBe(expectedSearchRoute);
+ expectToBe(bibliographyService.resourcesRoute, expectedResourcesRoute);
+ expectToBe(bibliographyService.searchRoute, expectedSearchRoute);
});
it("... should have empty 'httpGetUrl' (inherited from ApiService)", () => {
- expect(bibliographyService.httpGetUrl).toBeDefined();
- expect(bibliographyService.httpGetUrl).not.toBeTruthy();
- expect(bibliographyService.httpGetUrl).withContext(`should be empty string`).toBe('');
+ expectToBe(bibliographyService.httpGetUrl, '');
});
});
@@ -122,8 +105,7 @@ describe('BibliographyService (DONE)', () => {
httpClient.get
('/foo/bar').subscribe({
next: data => {
- expect(data).toBeTruthy();
- expect(data).withContext(`should equal ${testData}`).toEqual(testData);
+ expectToEqual(data, testData);
},
});
@@ -133,7 +115,7 @@ describe('BibliographyService (DONE)', () => {
});
// Check for GET request
- expect(call.request.method).toEqual('GET');
+ expectToEqual(call.request.method, 'GET');
// Respond with mocked data
call.flush(testData);
@@ -159,9 +141,9 @@ describe('BibliographyService (DONE)', () => {
`GET to ${expectedUrl}`
);
- expect(call.request.method).withContext('should be GET').toBe('GET');
- expect(call.request.responseType).withContext('should be json').toBe('json');
- expect(call.request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(call.request.method, 'GET');
+ expectToBe(call.request.responseType, 'json');
+ expectToBe(call.request.url, expectedUrl);
}));
it('... should set filter params for GET request', waitForAsync(() => {
@@ -177,22 +159,17 @@ describe('BibliographyService (DONE)', () => {
`GET to ${expectedUrl}`
);
- expect(call.request.method).withContext('should be GET').toBe('GET');
- expect(call.request.responseType).withContext('should be json').toBe('json');
- expect(call.request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(call.request.method, 'GET');
+ expectToBe(call.request.responseType, 'json');
+ expectToBe(call.request.url, expectedUrl);
+
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 5').toBe(5);
- expect(call.request.params.get('searchtype')).withContext('should be extended').toBe('extended');
- expect(call.request.params.get('filter_by_project'))
- .withContext(`should be ${expectedProjectId}`)
- .toBe(expectedProjectId);
- expect(call.request.params.get('filter_by_restype'))
- .withContext(`should be ${expectedResTypeId}`)
- .toBe(expectedResTypeId);
- expect(call.request.params.get('property_id'))
- .withContext(`should be ${expectedBibShortTitlePropertyId}`)
- .toBe(expectedBibShortTitlePropertyId);
- expect(call.request.params.get('compop')).withContext('should be EXISTS').toBe('EXISTS');
+ expectToBe(call.request.params.keys().length, 5);
+ expectToBe(call.request.params.get('searchtype'), 'extended');
+ expectToBe(call.request.params.get('filter_by_project'), expectedProjectId);
+ expectToBe(call.request.params.get('filter_by_restype'), expectedResTypeId);
+ expectToBe(call.request.params.get('property_id'), expectedBibShortTitlePropertyId);
+ expectToBe(call.request.params.get('compop'), 'EXISTS');
}));
it('... should call getApiResponse (via ApiService) with filter params', waitForAsync(() => {
@@ -225,10 +202,7 @@ describe('BibliographyService (DONE)', () => {
bibliographyService.getBibliographyList().subscribe({
next: (response: SearchResponseJson) => {
- expect(response).toBeTruthy();
- expect(response)
- .withContext(`shoud equal ${expectedSearchResponseJson}`)
- .toEqual(expectedSearchResponseJson);
+ expectToEqual(response, expectedSearchResponseJson);
},
});
}));
@@ -260,9 +234,7 @@ describe('BibliographyService (DONE)', () => {
expectedQueryPath,
expectedQueryHttpParams,
]);
- expect(err)
- .withContext(`shoud equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
@@ -286,7 +258,7 @@ describe('BibliographyService (DONE)', () => {
// Expect one request to url with given settings
httpTestingController.expectOne((req: HttpRequest) => {
expect(req.params).toBeDefined();
- expect(req.params.keys().length).withContext('should be 0').toBe(0);
+ expectToBe(req.params.keys().length, 0);
return req.method === 'GET' && req.responseType === 'json' && req.url === expectedUrl;
}, `GET to ${expectedUrl}`);
@@ -320,10 +292,7 @@ describe('BibliographyService (DONE)', () => {
bibliographyService.getBibliographyItemDetail(expectedResourceId).subscribe({
next: (response: ResourceFullResponseJson) => {
- expect(response).toBeTruthy();
- expect(response)
- .withContext(`should equal ${expectedResourceFullResponseJson}`)
- .toEqual(expectedResourceFullResponseJson);
+ expectToEqual(response, expectedResourceFullResponseJson);
},
});
}));
@@ -351,9 +320,7 @@ describe('BibliographyService (DONE)', () => {
expectedQueryPath,
expectedQueryHttpParams,
]);
- expect(err)
- .withContext(`shoud equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
diff --git a/src/app/views/data-view/services/data-api.service.spec.ts b/src/app/views/data-view/services/data-api.service.spec.ts
index dedc2cf69..e584e70e8 100644
--- a/src/app/views/data-view/services/data-api.service.spec.ts
+++ b/src/app/views/data-view/services/data-api.service.spec.ts
@@ -8,7 +8,7 @@ import { JsonConvert } from 'json2typescript';
import { of as observableOf, throwError as observableThrowError } from 'rxjs';
import Spy = jasmine.Spy;
-import { expectSpyCall } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, expectToEqual } from '@testing/expect-helper';
import {
mockPropertyTypesInResourceClassResponseJson,
mockResourceContextResponseJson,
@@ -37,9 +37,8 @@ import { DataApiService } from './data-api.service';
// Helper function
function expectParams(call: TestRequest, param: string, expectedValue: string[], length?: number) {
- expect(call.request.params.getAll(param)).toBeTruthy();
- expect(call.request.params.getAll(param).length).withContext(`should be ${length}`).toBe(length);
- expect(call.request.params.getAll(param)).withContext(`should equal ${expectedValue}`).toEqual(expectedValue);
+ expectToBe(call.request.params.getAll(param).length, length);
+ expectToEqual(call.request.params.getAll(param), expectedValue);
}
describe('DataApiService (DONE)', () => {
@@ -139,55 +138,38 @@ describe('DataApiService (DONE)', () => {
it('... injected service should use provided mockValue', () => {
const conversionService = TestBed.inject(ConversionService);
- expect(mockConversionService === conversionService)
- .withContext('should be true')
- .toBeTrue();
+ expectToBe(mockConversionService === conversionService, true);
});
describe('default values', () => {
it('... should have serviceName', () => {
const expectedServiceName = 'DataApiService';
- expect(dataApiService.serviceName).toBeDefined();
- expect(dataApiService.serviceName)
- .withContext(`should be ${expectedServiceName}`)
- .toBe(expectedServiceName);
+ expectToBe(dataApiService.serviceName, expectedServiceName);
});
it('... should have projectId', () => {
- expect(dataApiService.projectId).toBeDefined();
- expect(dataApiService.projectId).withContext(`should be ${expectedProjectId}`).toBe(expectedProjectId);
+ expectToBe(dataApiService.projectId, expectedProjectId);
});
it('... should have vocabularyId', () => {
- expect(dataApiService.vocabularyId).toBeDefined();
- expect(dataApiService.vocabularyId)
- .withContext(`should be ${expectedVocabularyId}`)
- .toBe(expectedVocabularyId);
+ expectToBe(dataApiService.vocabularyId, expectedVocabularyId);
});
it('... should have defaultLanguage', () => {
- expect(dataApiService.defaultLanguage).toBeDefined();
- expect(dataApiService.defaultLanguage)
- .withContext(`should be ${expectedDefaultLanguage}`)
- .toBe(expectedDefaultLanguage);
+ expectToBe(dataApiService.defaultLanguage, expectedDefaultLanguage);
});
it('... should have resourceSuffix', () => {
- expect(dataApiService.resourceSuffix).toBeDefined();
- expect(dataApiService.resourceSuffix)
- .withContext(`should be ${expectedResourceSuffix}`)
- .toBe(expectedResourceSuffix);
+ expectToBe(dataApiService.resourceSuffix, expectedResourceSuffix);
});
it('... should have routes', () => {
- expect(dataApiService.routes).toBeDefined();
- expect(dataApiService.routes).withContext(`should be ${expectedRoutes}`).toEqual(expectedRoutes);
+ expectToEqual(dataApiService.routes, expectedRoutes);
});
it("... should have empty 'httpGetUrl' (inherited from ApiService)", () => {
- expect(dataApiService.httpGetUrl).toBeDefined();
- expect(dataApiService.httpGetUrl).withContext('should be empty string').toBe('');
+ expectToBe(dataApiService.httpGetUrl, '');
});
});
@@ -197,8 +179,7 @@ describe('DataApiService (DONE)', () => {
httpClient.get('/foo/bar').subscribe({
next: data => {
- expect(data).toBeTruthy();
- expect(data).withContext(`should equal ${testData}`).toEqual(testData);
+ expectToEqual(data, testData);
},
});
@@ -208,7 +189,7 @@ describe('DataApiService (DONE)', () => {
});
// Check for GET request
- expect(call.request.method).withContext(`should be GET`).toBe('GET');
+ expectToBe(call.request.method, 'GET');
// Respond with mocked data
call.flush(testData);
@@ -430,14 +411,9 @@ describe('DataApiService (DONE)', () => {
`GET to ${expectedUrl}`
);
- expect(call.request.method).toBeTruthy();
- expect(call.request.method).withContext('should be GET').toBe('GET');
-
- expect(call.request.responseType).toBeTruthy();
- expect(call.request.responseType).withContext('should be json').toBe('json');
-
- expect(call.request.url).toBeTruthy();
- expect(call.request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(call.request.method, 'GET');
+ expectToBe(call.request.responseType, 'json');
+ expectToBe(call.request.url, expectedUrl);
}));
it('... for Extended search with provided object (url does not include query)', waitForAsync(() => {
@@ -462,14 +438,9 @@ describe('DataApiService (DONE)', () => {
`GET to ${expectedUrl}`
);
- expect(call.request.method).toBeTruthy();
- expect(call.request.method).withContext('should be GET').toBe('GET');
-
- expect(call.request.responseType).toBeTruthy();
- expect(call.request.responseType).withContext('should be json').toBe('json');
-
- expect(call.request.url).toBeTruthy();
- expect(call.request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(call.request.method, 'GET');
+ expectToBe(call.request.responseType, 'json');
+ expectToBe(call.request.url, expectedUrl);
}));
});
@@ -492,7 +463,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 5').toBe(5);
+ expectToBe(call.request.params.keys().length, 5);
expectParams(call, 'searchtype', ['fulltext'], 1);
expectParams(call, 'filter_by_project', [expectedProjectId], 1);
@@ -521,7 +492,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 6').toBe(6);
+ expectToBe(call.request.params.keys().length, 6);
expectParams(call, 'searchtype', ['extended'], 1);
expectParams(call, 'filter_by_project', [expectedProjectId], 1);
@@ -554,7 +525,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 5').toBe(5);
+ expectToBe(call.request.params.keys().length, 5);
expectParams(call, 'searchtype', ['fulltext'], 1);
expectParams(call, 'filter_by_project', [expectedProjectId], 1);
@@ -592,7 +563,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 8').toBe(8);
+ expectToBe(call.request.params.keys().length, 8);
expectParams(call, 'searchtype', ['extended'], 1);
expectParams(call, 'filter_by_project', [expectedProjectId], 1);
@@ -634,7 +605,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 8').toBe(8);
+ expectToBe(call.request.params.keys().length, 8);
expectParams(call, 'searchtype', ['extended'], 1);
expectParams(call, 'filter_by_project', [expectedProjectId], 1);
@@ -677,7 +648,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 9').toBe(9);
+ expectToBe(call.request.params.keys().length, 9);
expectParams(call, 'searchtype', ['extended'], 1);
expectParams(call, 'filter_by_project', [expectedProjectId], 1);
@@ -724,7 +695,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 9').toBe(9);
+ expectToBe(call.request.params.keys().length, 9);
expectParams(call, 'searchtype', ['extended'], 1);
expectParams(call, 'filter_by_project', [expectedProjectId], 1);
@@ -828,10 +799,7 @@ describe('DataApiService (DONE)', () => {
dataApiService.getSearchData(expectedSearchParams).subscribe({
next: (response: SearchResponseJson) => {
- expect(response).toBeTruthy();
- expect(response)
- .withContext(`should equal ${expectedSearchResponseConverted}`)
- .toEqual(expectedSearchResponseConverted);
+ expectToEqual(response, expectedSearchResponseConverted);
},
});
}));
@@ -866,9 +834,7 @@ describe('DataApiService (DONE)', () => {
expectedQueryPath,
expectedQueryHttpParams,
]);
- expect(err)
- .withContext(`should equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
@@ -955,7 +921,7 @@ describe('DataApiService (DONE)', () => {
req => req.url.match(re) && req.method === 'GET' && req.responseType === 'json'
);
- expect(calls.length).withContext('should be 2 calls').toBe(2);
+ expectToBe(calls.length, 2);
}));
it('... the first request being a ResourceFullResponse request', waitForAsync(() => {
@@ -971,20 +937,15 @@ describe('DataApiService (DONE)', () => {
req => req.url.match(re) && req.method === 'GET' && req.responseType === 'json'
);
- expect(calls.length).withContext('should be 2 calls').toBe(2);
+ expectToBe(calls.length, 2);
// Call to GET https://www.salsah.org/api/resources/11398_-_local (ResourceFullResponseJson)
- expect(calls[0].request.method).toBeTruthy();
- expect(calls[0].request.method).withContext('should be GET').toBe('GET');
-
- expect(calls[0].request.responseType).toBeTruthy();
- expect(calls[0].request.responseType).withContext('should be json').toBe('json');
-
- expect(calls[0].request.url).toBeTruthy();
- expect(calls[0].request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(calls[0].request.method, 'GET');
+ expectToBe(calls[0].request.responseType, 'json');
+ expectToBe(calls[0].request.url, expectedUrl);
expect(calls[0].request.params).toBeDefined();
- expect(calls[0].request.params.keys().length).withContext('should be 0').toBe(0);
+ expectToBe(calls[0].request.params.keys().length, 0);
}));
it('... the second request being a ResourceContextResponse request', waitForAsync(() => {
@@ -1000,20 +961,15 @@ describe('DataApiService (DONE)', () => {
req => req.url.match(re) && req.method === 'GET' && req.responseType === 'json'
);
- expect(calls.length).withContext('should be 2 calls').toBe(2);
+ expectToBe(calls.length, 2);
// Call to GET https://www.salsah.org/api/resources/11398_-_local?reqtype=context (ResourceContextResponseJson)
- expect(calls[1].request.method).toBeTruthy();
- expect(calls[1].request.method).withContext('should be GET').toBe('GET');
-
- expect(calls[1].request.responseType).toBeTruthy();
- expect(calls[1].request.responseType).withContext('should be json').toBe('json');
-
- expect(calls[1].request.url).toBeTruthy();
- expect(calls[1].request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(calls[0].request.method, 'GET');
+ expectToBe(calls[0].request.responseType, 'json');
+ expectToBe(calls[0].request.url, expectedUrl);
expect(calls[1].request.params).toBeDefined();
- expect(calls[1].request.params.keys().length).withContext('should be 1').toBe(1);
+ expectToBe(calls[1].request.params.keys().length, 1);
expectParams(calls[1], 'reqtype', ['context'], 1);
}));
@@ -1027,7 +983,7 @@ describe('DataApiService (DONE)', () => {
dataApiService.getResourceData(expectedResourceId).subscribe((response: ResourceData) => {
// Two calls
- expect(getApiResponseSpy.calls.all().length).withContext('should be 2 calls').toBe(2);
+ expectToBe(getApiResponseSpy.calls.all().length, 2);
});
// Expect two requests to url with given settings
@@ -1049,26 +1005,15 @@ describe('DataApiService (DONE)', () => {
dataApiService.getResourceData(expectedResourceId).subscribe({
next: () => {
// Two calls
- expect(getApiResponseSpy.calls.all().length).withContext('should be 2 calls').toBe(2);
+ expectToBe(getApiResponseSpy.calls.all().length, 2);
// Shortcut
const firstCallArgs = getApiResponseSpy.calls.allArgs()[0];
// Check args of call
- expect(firstCallArgs[0].name).toBeTruthy();
- expect(firstCallArgs[0].name)
- .withContext('should be ResourceFullResponseJson')
- .toBe('ResourceFullResponseJson');
-
- expect(firstCallArgs[1]).toBeTruthy();
- expect(firstCallArgs[1])
- .withContext(`should be ${expectedQueryPath}`)
- .toBe(expectedQueryPath);
-
- expect(firstCallArgs[2]).toBeTruthy();
- expect(firstCallArgs[2])
- .withContext(`should equal ${expectedQueryHttpParams}`)
- .toEqual(expectedQueryHttpParams);
+ expectToBe(firstCallArgs[0].name, 'ResourceFullResponseJson');
+ expectToBe(firstCallArgs[1], expectedQueryPath);
+ expectToEqual(firstCallArgs[2], expectedQueryHttpParams);
},
});
@@ -1091,26 +1036,15 @@ describe('DataApiService (DONE)', () => {
dataApiService.getResourceData(expectedResourceId).subscribe({
next: () => {
// Two calls
- expect(getApiResponseSpy.calls.all().length).withContext('should be 2 calls').toBe(2);
+ expectToBe(getApiResponseSpy.calls.all().length, 2);
// Shortcut
const secondCallArgs = getApiResponseSpy.calls.allArgs()[1];
// Check args of call
- expect(secondCallArgs[0].name).toBeTruthy();
- expect(secondCallArgs[0].name)
- .withContext('should be ResourceContextResponseJson')
- .toBe('ResourceContextResponseJson');
-
- expect(secondCallArgs[1]).toBeTruthy();
- expect(secondCallArgs[1])
- .withContext(`should be ${expectedQueryPath}`)
- .toBe(expectedQueryPath);
-
- expect(secondCallArgs[2]).toBeTruthy();
- expect(secondCallArgs[2])
- .withContext(`should equal ${expectedQueryHttpParams}`)
- .toEqual(expectedQueryHttpParams);
+ expectToBe(secondCallArgs[0].name, 'ResourceContextResponseJson');
+ expectToBe(secondCallArgs[1], expectedQueryPath);
+ expectToEqual(secondCallArgs[2], expectedQueryHttpParams);
},
});
@@ -1140,11 +1074,8 @@ describe('DataApiService (DONE)', () => {
dataApiService.getResourceData(expectedResourceId).subscribe({
next: (resourceData: ResourceData) => {
- expect(getApiResponseSpy.calls.all().length).withContext('should be 2 calls').toBe(2);
- expect(resourceData).toBeTruthy();
- expect(resourceData)
- .withContext(`should equal ${expectedResourceData}`)
- .toEqual(expectedResourceData);
+ expectToBe(getApiResponseSpy.calls.all().length, 2);
+ expectToEqual(resourceData, expectedResourceData);
},
});
}));
@@ -1175,10 +1106,8 @@ describe('DataApiService (DONE)', () => {
next: () => fail(expectedErrorMsg),
error: (err: ApiServiceError) => {
// Two calls
- expect(getApiResponseSpy.calls.all().length).withContext('should be 2 calls').toBe(2);
- expect(err)
- .withContext(`should equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToBe(getApiResponseSpy.calls.all().length, 2);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
@@ -1194,10 +1123,8 @@ describe('DataApiService (DONE)', () => {
next: () => fail(expectedErrorMsg),
error: (err: ApiServiceError) => {
// Two calls
- expect(getApiResponseSpy.calls.all().length).withContext('should be 2 calls').toBe(2);
- expect(err)
- .withContext(`should equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToBe(getApiResponseSpy.calls.all().length, 2);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
@@ -1213,10 +1140,8 @@ describe('DataApiService (DONE)', () => {
next: () => fail(expectedErrorMsg),
error: (err: ApiServiceError) => {
// Two calls
- expect(getApiResponseSpy.calls.all().length).withContext('should be 2 calls').toBe(2);
- expect(err)
- .withContext(`should equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToBe(getApiResponseSpy.calls.all().length, 2);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
@@ -1244,14 +1169,9 @@ describe('DataApiService (DONE)', () => {
`GET to ${expectedUrl}`
);
- expect(call.request.method).toBeTruthy();
- expect(call.request.method).withContext('should be GET').toBe('GET');
-
- expect(call.request.responseType).toBeTruthy();
- expect(call.request.responseType).withContext('should be json').toBe('json');
-
- expect(call.request.url).toBeTruthy();
- expect(call.request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(call.request.method, 'GET');
+ expectToBe(call.request.responseType, 'json');
+ expectToBe(call.request.url, expectedUrl);
}));
it('... should set default query params for GET request', waitForAsync(() => {
@@ -1268,7 +1188,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 2').toBe(2);
+ expectToBe(call.request.params.keys().length, 2);
expectParams(call, 'vocabulary', [expectedVocabularyId], 1);
expectParams(call, 'lang', [expectedDefaultLanguage], 1);
@@ -1302,9 +1222,7 @@ describe('DataApiService (DONE)', () => {
dataApiService.getResourceTypes().subscribe({
next: (restypes: ResourceTypesInVocabularyResponseJson) => {
expect(restypes).toBeTruthy();
- expect(restypes)
- .withContext(`should equal ${expectedResourceTypesInVocabularyResponseJson}`)
- .toEqual(expectedResourceTypesInVocabularyResponseJson);
+ expectToEqual(restypes, expectedResourceTypesInVocabularyResponseJson);
},
});
}));
@@ -1333,9 +1251,7 @@ describe('DataApiService (DONE)', () => {
expectedQueryPath,
expectedQueryHttpParams,
]);
- expect(err)
- .withContext(`should equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
@@ -1422,14 +1338,9 @@ describe('DataApiService (DONE)', () => {
`GET to ${expectedUrl}`
);
- expect(call.request.method).toBeTruthy();
- expect(call.request.method).withContext('should be GET').toBe('GET');
-
- expect(call.request.responseType).toBeTruthy();
- expect(call.request.responseType).withContext('should be json').toBe('json');
-
- expect(call.request.url).toBeTruthy();
- expect(call.request.url).withContext(`should be ${expectedUrl}`).toBe(expectedUrl);
+ expectToBe(call.request.method, 'GET');
+ expectToBe(call.request.responseType, 'json');
+ expectToBe(call.request.url, expectedUrl);
}));
it('... should set default query params for GET request', waitForAsync(() => {
@@ -1447,7 +1358,7 @@ describe('DataApiService (DONE)', () => {
);
expect(call.request.params).toBeDefined();
- expect(call.request.params.keys().length).withContext('should be 1').toBe(1);
+ expectToBe(call.request.params.keys().length, 1);
expectParams(call, 'restype', [expectedRestype], 1);
}));
@@ -1482,9 +1393,7 @@ describe('DataApiService (DONE)', () => {
dataApiService.getPropertyListsByResourceType(expectedRestype).subscribe({
next: (propertyList: PropertyTypesInResourceClassResponseJson) => {
expect(propertyList).toBeTruthy();
- expect(propertyList)
- .withContext(`should equal ${expectedPropertyTypesInResourceClassResponseJson}`)
- .toEqual(expectedPropertyTypesInResourceClassResponseJson);
+ expectToEqual(propertyList, expectedPropertyTypesInResourceClassResponseJson);
},
});
}));
@@ -1512,9 +1421,7 @@ describe('DataApiService (DONE)', () => {
expectedQueryPath,
expectedQueryHttpParams,
]);
- expect(err)
- .withContext(`should equal ${expectedApiServiceError}`)
- .toEqual(expectedApiServiceError);
+ expectToEqual(err, expectedApiServiceError);
},
});
}));
diff --git a/src/app/views/edition-view/data/edition-assets.data.ts b/src/app/views/edition-view/data/edition-assets.data.ts
index 9dd7e347a..c1619d279 100644
--- a/src/app/views/edition-view/data/edition-assets.data.ts
+++ b/src/app/views/edition-view/data/edition-assets.data.ts
@@ -14,9 +14,11 @@ export const EDITION_ASSETS_DATA = {
* The names of the edition assets JSON files.
*/
FILES: {
+ complexesFile: 'edition-complexes.json',
folioConvoluteFile: 'folio-convolute.json',
graphFile: 'graph.json',
introFile: 'intro.json',
+ prefaceFile: 'preface.json',
rowTablesFile: 'row-tables.json',
sourceListFile: 'source-list.json',
sourceDescriptionListFile: 'source-description.json',
diff --git a/src/app/views/edition-view/data/edition-complexes.data.ts b/src/app/views/edition-view/data/edition-complexes.data.ts
deleted file mode 100644
index f8ed7c7b7..000000000
--- a/src/app/views/edition-view/data/edition-complexes.data.ts
+++ /dev/null
@@ -1,774 +0,0 @@
-import { AppConfig } from '@awg-app/app.config';
-import {
- EDITION_CATALOGUE_TYPE_CONSTANTS,
- EDITION_ROUTE_CONSTANTS,
- EDITION_TYPE_CONSTANTS,
-} from '@awg-views/edition-view/edition-route-constants';
-import { EditionComplex } from '@awg-views/edition-view/models';
-
-/**
- * The EditionComplexes class.
- *
- * It is used in the context of the edition view
- * to store information about the edition complexes.
- */
-export class EDITION_COMPLEXES {
- /**
- * An EditionComplex object for M 22.
- */
- static readonly M22: EditionComplex = new EditionComplex(
- {
- title: 'Studienkomposition für Klavier / Streichquartett',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '22',
- },
- {
- editors: [
- {
- name: 'Michael Matter',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '21. März 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_2,
- EDITION_ROUTE_CONSTANTS.SECTION_2A,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 30.
- */
- static readonly M30: EditionComplex = new EditionComplex(
- {
- title: 'Studienkomposition für Klavier',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '30',
- },
- {
- editors: [
- {
- name: 'Michael Matter',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '19. Januar 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_2,
- EDITION_ROUTE_CONSTANTS.SECTION_2A,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 31.
- */
- static readonly M31: EditionComplex = new EditionComplex(
- {
- title: 'Studienkomposition für Klavier',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '31',
- },
- {
- editors: [
- {
- name: 'Michael Matter',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '19. Januar 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_2,
- EDITION_ROUTE_CONSTANTS.SECTION_2A,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 34.
- */
- static readonly M34: EditionComplex = new EditionComplex(
- {
- title: 'Studienkomposition für Klavier',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '34',
- },
- {
- editors: [
- {
- name: 'Michael Matter',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Mai 2023',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_2,
- EDITION_ROUTE_CONSTANTS.SECTION_2A,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 35/42.
- */
- static readonly M35_42: EditionComplex = new EditionComplex(
- {
- title: 'Studienkomposition für Klavier',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '35/42',
- },
- {
- editors: [
- {
- name: 'Michael Matter',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '8. Februar 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_2,
- EDITION_ROUTE_CONSTANTS.SECTION_2A,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 37.
- */
- static readonly M37: EditionComplex = new EditionComplex(
- {
- title: 'Studienkomposition für Klavier',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '37',
- },
- {
- editors: [
- {
- name: 'Michael Matter',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '19. Januar 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_2,
- EDITION_ROUTE_CONSTANTS.SECTION_2A,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 133.
- */
- static readonly M133: EditionComplex = new EditionComplex(
- {
- title: '„Dies ist ein Lied“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '133',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 134.
- */
- static readonly M134: EditionComplex = new EditionComplex(
- {
- title: '„Im Windesweben“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '134',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 135.
- */
- static readonly M135: EditionComplex = new EditionComplex(
- {
- title: '„An Bachesranft“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '135',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 136.
- */
- static readonly M136: EditionComplex = new EditionComplex(
- {
- title: '„Im Morgentaun“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '136',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 137.
- */
- static readonly M137: EditionComplex = new EditionComplex(
- {
- title: '„Kahl reckt der Baum“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '137',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 138.
- */
- static readonly M138: EditionComplex = new EditionComplex(
- {
- title: 'Eingang („Welt der Gestalten“)',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '138',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 139.
- */
- static readonly M139: EditionComplex = new EditionComplex(
- {
- title: '„Noch zwingt mich Treue“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '139',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 140.
- */
- static readonly M140: EditionComplex = new EditionComplex(
- {
- title: '„Ja Heil und Dank dir“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '140',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 141.
- */
- static readonly M141: EditionComplex = new EditionComplex(
- {
- title: '„So ich traurig bin“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '141',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 142.
- */
- static readonly M142: EditionComplex = new EditionComplex(
- {
- title: '„Ihr tratet zu dem Herde“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '142',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 143.
- */
- static readonly M143: EditionComplex = new EditionComplex(
- {
- title: '„Erwachen aus dem tiefsten Traumesschoße“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '143',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 144.
- */
- static readonly M144: EditionComplex = new EditionComplex(
- {
- title: 'Kunfttag I („Dem bist du Kind“)',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '144',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 145.
- */
- static readonly M145: EditionComplex = new EditionComplex(
- {
- title: 'Trauer I („So wart bis ich dies dir noch künde“)',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '145',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 146.
- */
- static readonly M146: EditionComplex = new EditionComplex(
- {
- title: '„Das lockere Saatgefilde“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '146',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 212.
- */
- static readonly M212: EditionComplex = new EditionComplex(
- {
- title: '„Der Tag ist vergangen“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '212',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '---',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 213.
- */
- static readonly M213: EditionComplex = new EditionComplex(
- {
- title: '„Schien mir’s, als ich sah die Sonne“',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '213',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '---',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 216.
- */
- static readonly M216: EditionComplex = new EditionComplex(
- {
- title: 'Gleich und Gleich („Ein Blumenglöckchen“)',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '216',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '---',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for M 217.
- */
- static readonly M217: EditionComplex = new EditionComplex(
- {
- title: 'Die geheimnisvolle Flöte („An einem Abend“)',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
- catalogueNumber: '217',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '---',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 3.
- */
- static readonly OP3: EditionComplex = new EditionComplex(
- {
- title: 'Fünf Lieder aus Der siebente Ring von Stefan George',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '3',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 4.
- */
- static readonly OP4: EditionComplex = new EditionComplex(
- {
- title: 'Fünf Lieder nach Gedichten von Stefan George',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '4',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Juni 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 12.
- */
- static readonly OP12: EditionComplex = new EditionComplex(
- {
- title: 'Vier Lieder',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '12',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '9. April 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 19.
- */
- static readonly OP19: EditionComplex = new EditionComplex(
- {
- title: 'Zwei Lieder für gemischten Chor und Ensemble',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '19',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Mai 2023',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_3,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 22.
- */
- static readonly OP22: EditionComplex = new EditionComplex(
- {
- title: 'Quartett für Geige, Klarinette, Tenorsaxophon und Klavier',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '22',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Mai 2023',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_2,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 23.
- */
- static readonly OP23: EditionComplex = new EditionComplex(
- {
- title: 'Drei Gesänge aus Viae Inviae von Hildegard Jone',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '23',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '17. April 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 24.
- */
- static readonly OP24: EditionComplex = new EditionComplex(
- {
- title: 'Konzert für neun Instrumente',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '24',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Mai 2023',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_1,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 25.
- */
- static readonly OP25: EditionComplex = new EditionComplex(
- {
- title: 'Drei Lieder nach Gedichten von Hildegard Jone',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '25',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '17. April 2024',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-
- /**
- * An EditionComplex object for Opus 27.
- */
- static readonly OP27: EditionComplex = new EditionComplex(
- {
- title: 'Variationen für Klavier',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
- catalogueNumber: '27',
- },
- {
- editors: [
- {
- name: 'Thomas Ahrend',
- homepage: AppConfig.AWG_PROJECT_URL + 'index.php?id=3',
- },
- ],
- lastModified: '6. Mai 2023',
- },
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_2,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
- );
-}
diff --git a/src/app/views/edition-view/data/edition-glyphs.data.ts b/src/app/views/edition-view/data/edition-glyphs.data.ts
index 7e8a15345..1ba65657c 100644
--- a/src/app/views/edition-view/data/edition-glyphs.data.ts
+++ b/src/app/views/edition-view/data/edition-glyphs.data.ts
@@ -83,6 +83,33 @@ export const EDITION_GLYPHS_DATA = {
hex: '\uD834\uDD91\uD834\uDD91\uD834\uDD91',
},
+ /**
+ * The glyph of a musical mezzo forte symbol.
+ * Cf. https://graphemica.com/%F0%9D%86%90
+ */
+ MEZZOFORTE: {
+ alt: '[mf]',
+ hex: '\uD834\uDD90\uD834\uDD91',
+ },
+
+ /**
+ * The glyph of a musical mezzo piano symbol.
+ * Cf. https://graphemica.com/%F0%9D%86%90
+ */
+ MEZZOPIANO: {
+ alt: '[mp]',
+ hex: '\uD834\uDD90\uD834\uDD8F',
+ },
+
+ /**
+ * The glyph of a musical pedal symbol.
+ * Cf. https://graphemica.com/%F0%9D%86%AE
+ */
+ PEDAL: {
+ alt: '[ped]',
+ hex: '\uD834\uDDAE',
+ },
+
/**
* The glyph of a musical pianissimo (double piano) symbol.
* Cf. https://graphemica.com/%F0%9D%86%8F
diff --git a/src/app/views/edition-view/data/edition-outline.data.ts b/src/app/views/edition-view/data/edition-outline.data.ts
deleted file mode 100644
index 256032cbc..000000000
--- a/src/app/views/edition-view/data/edition-outline.data.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
-import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
-import { EditionOutlineSeries } from '@awg-views/edition-view/models';
-
-/**
- * Object constant: EDITION_OUTLINE_DATA.
- *
- * It provides metadata for the outline structure of the edition.
- */
-export const EDITION_OUTLINE_DATA: EditionOutlineSeries[] = [
- {
- series: EDITION_ROUTE_CONSTANTS.SERIES_1,
- sections: [
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_1,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_2,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_3,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_4,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_5,
- complexes: {
- opus: [
- { complex: EDITION_COMPLEXES.OP3, disabled: false },
- { complex: EDITION_COMPLEXES.OP4, disabled: false },
- { complex: EDITION_COMPLEXES.OP12, disabled: false },
- { complex: EDITION_COMPLEXES.OP23, disabled: false },
- { complex: EDITION_COMPLEXES.OP25, disabled: false },
- ],
- mnr: [
- { complex: EDITION_COMPLEXES.M133, disabled: true },
- { complex: EDITION_COMPLEXES.M134, disabled: true },
- { complex: EDITION_COMPLEXES.M135, disabled: true },
- { complex: EDITION_COMPLEXES.M136, disabled: true },
- { complex: EDITION_COMPLEXES.M137, disabled: true },
- { complex: EDITION_COMPLEXES.M138, disabled: true },
- { complex: EDITION_COMPLEXES.M139, disabled: true },
- { complex: EDITION_COMPLEXES.M140, disabled: true },
- { complex: EDITION_COMPLEXES.M141, disabled: true },
- { complex: EDITION_COMPLEXES.M142, disabled: true },
- { complex: EDITION_COMPLEXES.M143, disabled: false },
- { complex: EDITION_COMPLEXES.M144, disabled: false },
- { complex: EDITION_COMPLEXES.M145, disabled: false },
- { complex: EDITION_COMPLEXES.M146, disabled: false },
- { complex: EDITION_COMPLEXES.M213, disabled: true },
- { complex: EDITION_COMPLEXES.M212, disabled: true },
- { complex: EDITION_COMPLEXES.M216, disabled: true },
- { complex: EDITION_COMPLEXES.M217, disabled: true },
- ],
- },
- disabled: false,
- },
- ],
- },
- {
- series: EDITION_ROUTE_CONSTANTS.SERIES_2,
- sections: [
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_1,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_2A,
- complexes: {
- opus: [],
- mnr: [
- { complex: EDITION_COMPLEXES.M22, disabled: false },
- { complex: EDITION_COMPLEXES.M30, disabled: false },
- { complex: EDITION_COMPLEXES.M31, disabled: false },
- { complex: EDITION_COMPLEXES.M34, disabled: false },
- { complex: EDITION_COMPLEXES.M35_42, disabled: false },
- { complex: EDITION_COMPLEXES.M37, disabled: false },
- ],
- },
- disabled: false,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_2B,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_3,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_4,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_5,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- ],
- },
- {
- series: EDITION_ROUTE_CONSTANTS.SERIES_3,
- sections: [
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_1,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_2,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_3,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SECTION_4,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- {
- section: EDITION_ROUTE_CONSTANTS.SERIES_3_SECTION_5,
- complexes: { opus: [], mnr: [] },
- disabled: true,
- },
- ],
- },
-];
diff --git a/src/app/views/edition-view/data/index.ts b/src/app/views/edition-view/data/index.ts
index e7bcf8d8b..850e7c141 100644
--- a/src/app/views/edition-view/data/index.ts
+++ b/src/app/views/edition-view/data/index.ts
@@ -8,17 +8,8 @@
*/
import { EDITION_ASSETS_DATA } from './edition-assets.data';
-import { EDITION_COMPLEXES } from './edition-complexes.data';
import { EDITION_FIRM_SIGNS_DATA } from './edition-firm-signs.data';
import { EDITION_GLYPHS_DATA } from './edition-glyphs.data';
import { EDITION_GRAPH_IMAGES_DATA } from './edition-graph-images.data';
-import { EDITION_OUTLINE_DATA } from './edition-outline.data';
-export {
- EDITION_ASSETS_DATA,
- EDITION_FIRM_SIGNS_DATA,
- EDITION_GLYPHS_DATA,
- EDITION_GRAPH_IMAGES_DATA,
- EDITION_OUTLINE_DATA,
- EDITION_COMPLEXES,
-};
+export { EDITION_ASSETS_DATA, EDITION_FIRM_SIGNS_DATA, EDITION_GLYPHS_DATA, EDITION_GRAPH_IMAGES_DATA };
diff --git a/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.html b/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.html
index 6ae70d510..f56c86500 100644
--- a/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.html
+++ b/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.html
@@ -13,7 +13,7 @@
Ediert von
@for (
- editor of complex.complex.responsibilityStatement.editors;
+ editor of complex.complex.respStatement.editors;
track editor.name;
let isLast = $last
) {
@@ -26,7 +26,7 @@
}
Versionsdatum:
- {{ complex.complex.responsibilityStatement.lastModified }}
+ {{ complex.complex.respStatement.lastModified }}
}
diff --git a/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.spec.ts b/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.spec.ts
index 03c111547..340b9bcd5 100644
--- a/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.spec.ts
+++ b/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.spec.ts
@@ -10,8 +10,8 @@ import {
} from '@testing/expect-helper';
import { RouterLinkStubDirective } from '@testing/router-stubs';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
-import { EditionOutlineComplex } from '@awg-views/edition-view/models';
+import { EditionOutlineComplexItem } from '@awg-views/edition-view/models';
+import { EditionComplexesService } from '@awg-views/edition-view/services';
import { EditionComplexCardComponent } from './edition-complex-card.component';
@@ -23,7 +23,11 @@ describe('EditionComplexCardComponent (DONE)', () => {
let linkDes: DebugElement[];
let routerLinks;
- let expectedComplexes: EditionOutlineComplex[];
+ let expectedComplexes: EditionOutlineComplexItem[];
+
+ beforeAll(() => {
+ EditionComplexesService.initializeEditionComplexesList();
+ });
beforeEach(async () => {
await TestBed.configureTestingModule({
@@ -38,11 +42,11 @@ describe('EditionComplexCardComponent (DONE)', () => {
// Test data
expectedComplexes = [
- { complex: EDITION_COMPLEXES.OP12, disabled: false },
- { complex: EDITION_COMPLEXES.OP23, disabled: false },
- { complex: EDITION_COMPLEXES.OP25, disabled: true },
- { complex: EDITION_COMPLEXES.M212, disabled: false },
- { complex: EDITION_COMPLEXES.M213, disabled: true },
+ { complex: EditionComplexesService.getEditionComplexById('OP12'), disabled: false },
+ { complex: EditionComplexesService.getEditionComplexById('OP23'), disabled: false },
+ { complex: EditionComplexesService.getEditionComplexById('OP25'), disabled: true },
+ { complex: EditionComplexesService.getEditionComplexById('M212'), disabled: false },
+ { complex: EditionComplexesService.getEditionComplexById('M213'), disabled: true },
];
});
@@ -82,139 +86,139 @@ describe('EditionComplexCardComponent (DONE)', () => {
describe('VIEW', () => {
it('... should have as many inner div.col as editionComplexes in outer div.row', () => {
- const rowDe = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
- getAndExpectDebugElementByCss(rowDe[0], 'div.col', expectedComplexes.length, expectedComplexes.length);
+ const rowDes = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
+ getAndExpectDebugElementByCss(rowDes[0], 'div.col', expectedComplexes.length, expectedComplexes.length);
});
it('... should have as many inner div.card.awg-edition-card as editionComplexes', () => {
- const rowDe = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
- const colDe = getAndExpectDebugElementByCss(
- rowDe[0],
+ const rowDes = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
+ const colDes = getAndExpectDebugElementByCss(
+ rowDes[0],
'div.col',
expectedComplexes.length,
expectedComplexes.length
);
- colDe.forEach(col => {
- getAndExpectDebugElementByCss(col, 'div.card.awg-edition-card', 1, 1);
+ colDes.forEach(colDe => {
+ getAndExpectDebugElementByCss(colDe, 'div.card.awg-edition-card', 1, 1);
});
});
it('... should have as many inner div.card-body as editionComplexes', () => {
- const rowDe = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
- const colDe = getAndExpectDebugElementByCss(
- rowDe[0],
+ const rowDes = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
+ const colDes = getAndExpectDebugElementByCss(
+ rowDes[0],
'div.col',
expectedComplexes.length,
expectedComplexes.length
);
- colDe.forEach(col => {
- const cardDe = getAndExpectDebugElementByCss(col, 'div.card.awg-edition-card', 1, 1);
- getAndExpectDebugElementByCss(cardDe[0], 'div.card-body', 1, 1);
+ colDes.forEach(colDe => {
+ const cardDes = getAndExpectDebugElementByCss(colDe, 'div.card.awg-edition-card', 1, 1);
+ getAndExpectDebugElementByCss(cardDes[0], 'div.card-body', 1, 1);
});
});
it('... should have as many inner h5.card-title as editionComplexes', () => {
- const rowDe = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
- const colDe = getAndExpectDebugElementByCss(
- rowDe[0],
+ const rowDes = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
+ const colDes = getAndExpectDebugElementByCss(
+ rowDes[0],
'div.col',
expectedComplexes.length,
expectedComplexes.length
);
- colDe.forEach(col => {
- const cardDe = getAndExpectDebugElementByCss(col, 'div.card.awg-edition-card', 1, 1);
- const cardBodyDe = getAndExpectDebugElementByCss(cardDe[0], 'div.card-body', 1, 1);
- getAndExpectDebugElementByCss(cardBodyDe[0], 'h5.card-title', 1, 1);
+ colDes.forEach(colDe => {
+ const cardDes = getAndExpectDebugElementByCss(colDe, 'div.card.awg-edition-card', 1, 1);
+ const cardBodyDes = getAndExpectDebugElementByCss(cardDes[0], 'div.card-body', 1, 1);
+ getAndExpectDebugElementByCss(cardBodyDes[0], 'h5.card-title', 1, 1);
});
});
it('... should text-mute card titles of disabled editionComplexes', () => {
- const rowDe = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
- const colDe = getAndExpectDebugElementByCss(
- rowDe[0],
+ const rowDes = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
+ const colDes = getAndExpectDebugElementByCss(
+ rowDes[0],
'div.col',
expectedComplexes.length,
expectedComplexes.length
);
- colDe.forEach((col, index) => {
- const cardTitleDe = getAndExpectDebugElementByCss(col, 'h5.card-title', 1, 1);
- const cardTitleEl = cardTitleDe[0].nativeElement;
+ colDes.forEach((colDe, index) => {
+ const cardTitleDes = getAndExpectDebugElementByCss(colDe, 'h5.card-title', 1, 1);
+ const cardTitleEl = cardTitleDes[0].nativeElement;
expectToBe(cardTitleEl.classList.contains('text-muted'), expectedComplexes[index].disabled);
});
});
it('... should display complex as card title in span.awg-edition-info-header-title', () => {
- const rowDe = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
- const colDe = getAndExpectDebugElementByCss(
- rowDe[0],
+ const rowDes = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
+ const colDes = getAndExpectDebugElementByCss(
+ rowDes[0],
'div.col',
expectedComplexes.length,
expectedComplexes.length
);
- colDe.forEach((col, index) => {
- const cardTitleDe = getAndExpectDebugElementByCss(col, 'h5.card-title', 1, 1);
- const headerDe = getAndExpectDebugElementByCss(
- cardTitleDe[0],
+ colDes.forEach((colDe, index) => {
+ const cardTitleDes = getAndExpectDebugElementByCss(colDe, 'h5.card-title', 1, 1);
+ const headerDes = getAndExpectDebugElementByCss(
+ cardTitleDes[0],
'span.awg-edition-info-header-title',
1,
1
);
- const headerEl = headerDe[0].nativeElement;
+ const headerEl = headerDes[0].nativeElement;
expectToBe(headerEl.innerHTML, expectedComplexes[index].complex.complexId.full);
});
});
it('... should have as many inner div.card-footer as editionComplexes', () => {
- const rowDe = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
- const colDe = getAndExpectDebugElementByCss(
- rowDe[0],
+ const rowDes = getAndExpectDebugElementByCss(compDe, 'div.row', 1, 1);
+ const colDes = getAndExpectDebugElementByCss(
+ rowDes[0],
'div.col',
expectedComplexes.length,
expectedComplexes.length
);
- colDe.forEach(col => {
- const cardDe = getAndExpectDebugElementByCss(col, 'div.card.awg-edition-card', 1, 1);
- getAndExpectDebugElementByCss(cardDe[0], 'div.card-footer', 1, 1);
+ colDes.forEach(colDe => {
+ const cardDes = getAndExpectDebugElementByCss(colDe, 'div.card.awg-edition-card', 1, 1);
+ getAndExpectDebugElementByCss(cardDes[0], 'div.card-footer', 1, 1);
});
});
it('... should have edition responsibility statement in div.card-footer if complex is not disabled', () => {
- const cardFooterDe = getAndExpectDebugElementByCss(
+ const cardFooterDes = getAndExpectDebugElementByCss(
compDe,
'div.card-footer',
expectedComplexes.length,
expectedComplexes.length
);
- cardFooterDe.forEach((cardFooter, index) => {
+ cardFooterDes.forEach((cardFooterDe, index) => {
if (!expectedComplexes[index].disabled) {
- getAndExpectDebugElementByCss(cardFooter, 'p.awg-edition-responsibility', 1, 1);
+ getAndExpectDebugElementByCss(cardFooterDe, 'p.awg-edition-responsibility', 1, 1);
} else {
- getAndExpectDebugElementByCss(cardFooter, 'p.awg-edition-responsibility', 0, 0);
+ getAndExpectDebugElementByCss(cardFooterDe, 'p.awg-edition-responsibility', 0, 0);
}
});
});
it('... should display as many editors in span.editor as there are editors', () => {
- const cardFooterDe = getAndExpectDebugElementByCss(
+ const cardFooterDes = getAndExpectDebugElementByCss(
compDe,
'div.card-footer',
expectedComplexes.length,
expectedComplexes.length
);
- cardFooterDe.forEach((cardFooter, index) => {
+ cardFooterDes.forEach((cardFooterDe, index) => {
if (!expectedComplexes[index].disabled) {
- const pDe = getAndExpectDebugElementByCss(cardFooter, 'p.awg-edition-responsibility', 1, 1);
- const editors = expectedComplexes[index].complex.responsibilityStatement.editors;
- const editorDe = getAndExpectDebugElementByCss(
- pDe[0],
+ const pDes = getAndExpectDebugElementByCss(cardFooterDe, 'p.awg-edition-responsibility', 1, 1);
+ const editors = expectedComplexes[index].complex.respStatement.editors;
+ const editorDes = getAndExpectDebugElementByCss(
+ pDes[0],
'span.editor',
editors.length,
editors.length
);
- editorDe.forEach((editor, editorIndex) => {
+ editorDes.forEach((editor, editorIndex) => {
const editorEl = editor.nativeElement;
expectToBe(editorEl.textContent.trim(), editors[editorIndex].name);
@@ -224,24 +228,24 @@ describe('EditionComplexCardComponent (DONE)', () => {
});
it('... should link to homepage of editors in span.editor', () => {
- const cardFooterDe = getAndExpectDebugElementByCss(
+ const cardFooterDes = getAndExpectDebugElementByCss(
compDe,
'div.card-footer',
expectedComplexes.length,
expectedComplexes.length
);
- cardFooterDe.forEach((cardFooter, index) => {
+ cardFooterDes.forEach((cardFooterDe, index) => {
if (!expectedComplexes[index].disabled) {
- const pDe = getAndExpectDebugElementByCss(cardFooter, 'p.awg-edition-responsibility', 1, 1);
- const editors = expectedComplexes[index].complex.responsibilityStatement.editors;
- const editorDe = getAndExpectDebugElementByCss(
- pDe[0],
+ const pDes = getAndExpectDebugElementByCss(cardFooterDe, 'p.awg-edition-responsibility', 1, 1);
+ const editors = expectedComplexes[index].complex.respStatement.editors;
+ const editorDes = getAndExpectDebugElementByCss(
+ pDes[0],
'span.editor',
editors.length,
editors.length
);
- editorDe.forEach((editor, editorIndex) => {
+ editorDes.forEach((editor, editorIndex) => {
const anchorDe = getAndExpectDebugElementByCss(editor, 'a', 1, 1);
const anchorEl = anchorDe[0].nativeElement;
@@ -252,70 +256,70 @@ describe('EditionComplexCardComponent (DONE)', () => {
});
it('... should display version date in span.version if complex is not disabled', () => {
- const cardFooterDe = getAndExpectDebugElementByCss(
+ const cardFooterDes = getAndExpectDebugElementByCss(
compDe,
'div.card-footer',
expectedComplexes.length,
expectedComplexes.length
);
- cardFooterDe.forEach((cardFooter, index) => {
+ cardFooterDes.forEach((cardFooterDe, index) => {
if (!expectedComplexes[index].disabled) {
- const pDe = getAndExpectDebugElementByCss(cardFooter, 'p.awg-edition-responsibility', 1, 1);
- const versionDe = getAndExpectDebugElementByCss(pDe[0], 'span.version', 1, 1);
- const versionEl = versionDe[0].nativeElement;
+ const pDes = getAndExpectDebugElementByCss(cardFooterDe, 'p.awg-edition-responsibility', 1, 1);
+ const versionDes = getAndExpectDebugElementByCss(pDes[0], 'span.version', 1, 1);
+ const versionEl = versionDes[0].nativeElement;
expectToBe(
versionEl.textContent.trim(),
- expectedComplexes[index].complex.responsibilityStatement.lastModified
+ expectedComplexes[index].complex.respStatement.lastModified
);
} else {
- getAndExpectDebugElementByCss(cardFooter, 'p.awg-edition-responsibility', 0, 0);
- getAndExpectDebugElementByCss(cardFooter, 'span.version', 0, 0);
+ getAndExpectDebugElementByCss(cardFooterDe, 'p.awg-edition-responsibility', 0, 0);
+ getAndExpectDebugElementByCss(cardFooterDe, 'span.version', 0, 0);
}
});
});
it('... should have text-end paragraph in div.card-footer for each complex', () => {
- const cardFooterDe = getAndExpectDebugElementByCss(
+ const cardFooterDes = getAndExpectDebugElementByCss(
compDe,
'div.card-footer',
expectedComplexes.length,
expectedComplexes.length
);
- cardFooterDe.forEach(cardFooter => {
- getAndExpectDebugElementByCss(cardFooter, 'p.text-end', 1, 1);
+ cardFooterDes.forEach(cardFooterDe => {
+ getAndExpectDebugElementByCss(cardFooterDe, 'p.text-end', 1, 1);
});
});
it('... should have a link to complex in text-end paragraph for each complex', () => {
- const pDe = getAndExpectDebugElementByCss(
+ const pDes = getAndExpectDebugElementByCss(
compDe,
'p.text-end',
expectedComplexes.length,
expectedComplexes.length
);
- pDe.forEach(p => {
- const linkDe = getAndExpectDebugElementByCss(p, 'a', 1, 1);
- const linkEl = linkDe[0].nativeElement;
+ pDes.forEach(pDe => {
+ const aDes = getAndExpectDebugElementByCss(pDe, 'a', 1, 1);
+ const aEl = aDes[0].nativeElement;
const expectedLinkText = 'Mehr ...';
- expectToBe(linkEl.textContent.trim(), expectedLinkText);
+ expectToBe(aEl.textContent.trim(), expectedLinkText);
});
});
it('... should disable links only for disabled editionComplexes', () => {
- const pDe = getAndExpectDebugElementByCss(
+ const pDes = getAndExpectDebugElementByCss(
compDe,
'p.text-end',
expectedComplexes.length,
expectedComplexes.length
);
- pDe.forEach((p, index) => {
- const linkDe = getAndExpectDebugElementByCss(p, 'a', 1, 1);
- const linkEl = linkDe[0].nativeElement;
+ pDes.forEach((pDe, index) => {
+ const aDes = getAndExpectDebugElementByCss(pDe, 'a', 1, 1);
+ const aEl = aDes[0].nativeElement;
- expectToBe(linkEl.classList.contains('disabled'), expectedComplexes[index].disabled);
+ expectToBe(aEl.classList.contains('disabled'), expectedComplexes[index].disabled);
});
});
});
@@ -347,7 +351,7 @@ describe('EditionComplexCardComponent (DONE)', () => {
const linkDe = linkDes[index];
const expectedRouterLink = [expectedComplexes[index].complex.baseRoute];
- expect(routerLink.navigatedTo).toBeNull();
+ expectToBe(routerLink.navigatedTo, null);
click(linkDe);
fixture.detectChanges();
diff --git a/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.ts b/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.ts
index 9d15f4b92..7b56a002d 100644
--- a/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.ts
+++ b/src/app/views/edition-view/edition-complex-card/edition-complex-card.component.ts
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
-import { EditionOutlineComplex } from '@awg-views/edition-view/models';
+import { EditionOutlineComplexItem } from '@awg-views/edition-view/models';
/**
* The EditionComplexCard component.
@@ -16,10 +16,10 @@ import { EditionOutlineComplex } from '@awg-views/edition-view/models';
})
export class EditionComplexCardComponent {
/**
- * Input variable: complex.
+ * Input variable: complexes.
*
- * It keeps the complex of the card view.
+ * It keeps the complexes of the card view.
*/
@Input()
- complexes: EditionOutlineComplex[];
+ complexes: EditionOutlineComplexItem[];
}
diff --git a/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.html b/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.html
index b7313b06d..e5ec34a2f 100644
--- a/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.html
+++ b/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.html
@@ -1,5 +1,3 @@
-
-
{{ jumbotronTitle }}
+
+
diff --git a/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.spec.ts b/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.spec.ts
index 01edffb64..8a4e462f8 100644
--- a/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.spec.ts
+++ b/src/app/views/edition-view/edition-jumbotron/edition-jumbotron.component.spec.ts
@@ -1,7 +1,7 @@
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import { expectToBe, getAndExpectDebugElementByCss } from '@testing/expect-helper';
import { EditionJumbotronComponent } from './edition-jumbotron.component';
@@ -39,8 +39,8 @@ describe('EditionJumbotronComponent', () => {
});
describe('VIEW', () => {
- it('... should have one div.awg-jumbotron-image', () => {
- getAndExpectDebugElementByCss(compDe, 'div.awg-jumbotron-image', 1, 1);
+ it('... should have one div.awg-jumbotron', () => {
+ getAndExpectDebugElementByCss(compDe, 'div.awg-jumbotron', 1, 1);
});
});
});
@@ -56,31 +56,26 @@ describe('EditionJumbotronComponent', () => {
});
it('... should have jumbotronId', () => {
- expect(component.jumbotronId).toBeDefined();
- expect(component.jumbotronId).withContext(`should be ${expectedId}`).toBe(expectedId);
+ expectToBe(component.jumbotronId, expectedId);
});
it('... should have jumbotronTitle', () => {
- expect(component.jumbotronTitle).toBeDefined();
- expect(component.jumbotronTitle).withContext(`should be ${expectedTitle}`).toBe(expectedTitle);
+ expectToBe(component.jumbotronTitle, expectedTitle);
});
describe('VIEW', () => {
- it('... should have an h1 in jumbotron', () => {
- const jumbotronDes = getAndExpectDebugElementByCss(compDe, 'div.awg-jumbotron-image', 1, 1);
+ it('... should have a heading (h3) in jumbotron', () => {
+ const jumbotronDes = getAndExpectDebugElementByCss(compDe, 'div.awg-jumbotron', 1, 1);
- getAndExpectDebugElementByCss(jumbotronDes[0], 'h1', 1, 1);
+ getAndExpectDebugElementByCss(jumbotronDes[0], 'h3', 1, 1);
});
- it('... should pass down `jumbotronId` and `jumbotronTitle`to jumbotron h1', () => {
- const headingDes = getAndExpectDebugElementByCss(compDe, 'div.awg-jumbotron-image > h1', 1, 1);
+ it('... should pass down `jumbotronId` and `jumbotronTitle`to jumbotron heading', () => {
+ const headingDes = getAndExpectDebugElementByCss(compDe, 'div.awg-jumbotron > h3', 1, 1);
const headingEl = headingDes[0].nativeElement;
- expect(headingEl.id).toBeTruthy();
- expect(headingEl.id).withContext(`should be ${expectedId}`).toBe(expectedId);
-
- expect(headingEl.textContent).toBeTruthy();
- expect(headingEl.textContent.trim()).withContext(`should be ${expectedTitle}`).toBe(expectedTitle);
+ expectToBe(headingEl.id, expectedId);
+ expectToBe(headingEl.textContent.trim(), expectedTitle);
});
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.spec.ts
index 457a97e72..57f742f37 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.spec.ts
@@ -5,17 +5,12 @@ import { ActivatedRoute, RouterModule } from '@angular/router';
import { Observable, ReplaySubject } from 'rxjs';
import Spy = jasmine.Spy;
-import { expectSpyCall } from '@testing/expect-helper';
+import { expectSpyCall, expectToEqual } from '@testing/expect-helper';
import { ActivatedRouteStub } from '@testing/router-stubs';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
-import {
- EDITION_CATALOGUE_TYPE_CONSTANTS,
- EDITION_ROUTE_CONSTANTS,
- EDITION_TYPE_CONSTANTS,
-} from '@awg-views/edition-view/edition-route-constants';
-import { EditionComplex } from '@awg-views/edition-view/models';
-import { EditionService } from '@awg-views/edition-view/services';
+import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
+import { EditionComplex, EditionComplexesList } from '@awg-views/edition-view/models';
+import { EditionComplexesService, EditionService } from '@awg-views/edition-view/services';
import { EditionComplexComponent } from './edition-complex.component';
@@ -29,25 +24,29 @@ describe('EditionComplexComponent (DONE)', () => {
let mockEditionComplexSubject: ReplaySubject
;
- let getEditionComplexFromRouteSpy: Spy;
- let editionServiceGetEditionComplexSpy: Spy;
- let editionServiceUpdateEditionComplexSpy: Spy;
- let editionServiceClearEditionComplexSpy: Spy;
+ let updateEditionComplexFromRouteSpy: Spy;
+ let editionServiceGetSelectedEditionComplexSpy: Spy;
+ let editionServiceUpdateSelectedEditionComplexSpy: Spy;
+ let editionServiceClearSelectedEditionComplexSpy: Spy;
- let expectedEditionComplexes: typeof EDITION_COMPLEXES;
+ let expectedEditionComplexes: EditionComplexesList;
let expectedSelectedEditionComplex: EditionComplex;
let expectedSelectedEditionComplexId: string;
const expectedEditionRouteConstants: typeof EDITION_ROUTE_CONSTANTS = EDITION_ROUTE_CONSTANTS;
+ beforeAll(() => {
+ EditionComplexesService.initializeEditionComplexesList();
+ });
+
beforeEach(async () => {
mockEditionComplexSubject = new ReplaySubject(1);
// Mock edition service
mockEditionService = {
- getEditionComplex: (): Observable => mockEditionComplexSubject.asObservable(),
- updateEditionComplex: (editionComplex: EditionComplex): void =>
+ getSelectedEditionComplex: (): Observable => mockEditionComplexSubject.asObservable(),
+ updateSelectedEditionComplex: (editionComplex: EditionComplex): void =>
mockEditionComplexSubject.next(editionComplex),
- clearEditionComplex: (): void => mockEditionComplexSubject.next(null),
+ clearSelectedEditionComplex: (): void => mockEditionComplexSubject.next(null),
};
// Mocked activated route
@@ -69,17 +68,26 @@ describe('EditionComplexComponent (DONE)', () => {
compDe = fixture.debugElement;
// TestData
- expectedEditionComplexes = EDITION_COMPLEXES;
- expectedSelectedEditionComplex = expectedEditionComplexes.OP12;
+
+ expectedSelectedEditionComplex = EditionComplexesService.getEditionComplexById('OP12');
expectedSelectedEditionComplexId = 'OP12';
// Spies on component functions
// `.and.callThrough` will track the spy down the nested describes, see
// https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3Eand.callThrough%3C/code%3E
- getEditionComplexFromRouteSpy = spyOn(component, 'getEditionComplexFromRoute').and.callThrough();
- editionServiceGetEditionComplexSpy = spyOn(mockEditionService, 'getEditionComplex').and.callThrough();
- editionServiceUpdateEditionComplexSpy = spyOn(mockEditionService, 'updateEditionComplex').and.callThrough();
- editionServiceClearEditionComplexSpy = spyOn(mockEditionService, 'clearEditionComplex').and.callThrough();
+ updateEditionComplexFromRouteSpy = spyOn(component, 'updateEditionComplexFromRoute').and.callThrough();
+ editionServiceGetSelectedEditionComplexSpy = spyOn(
+ mockEditionService,
+ 'getSelectedEditionComplex'
+ ).and.callThrough();
+ editionServiceUpdateSelectedEditionComplexSpy = spyOn(
+ mockEditionService,
+ 'updateSelectedEditionComplex'
+ ).and.callThrough();
+ editionServiceClearSelectedEditionComplexSpy = spyOn(
+ mockEditionService,
+ 'clearSelectedEditionComplex'
+ ).and.callThrough();
});
it('... should create', () => {
@@ -92,19 +100,16 @@ describe('EditionComplexComponent (DONE)', () => {
});
it('... should have `editionRouteConstants`', () => {
- expect(component.editionRouteConstants).toBeDefined();
- expect(component.editionRouteConstants)
- .withContext(`should be ${expectedEditionRouteConstants}`)
- .toBe(expectedEditionRouteConstants);
+ expectToEqual(component.editionRouteConstants, expectedEditionRouteConstants);
});
- describe('#getEditionComplexFromRoute()', () => {
- it('... should have a method `getEditionComplexFromRoute`', () => {
- expect(component.getEditionComplexFromRoute).toBeDefined();
+ describe('#updateEditionComplexFromRoute()', () => {
+ it('... should have a method `updateEditionComplexFromRoute`', () => {
+ expect(component.updateEditionComplexFromRoute).toBeDefined();
});
it('... should not have been called', () => {
- expectSpyCall(getEditionComplexFromRouteSpy, 0);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 0);
});
});
});
@@ -119,25 +124,40 @@ describe('EditionComplexComponent (DONE)', () => {
fixture.detectChanges();
});
- describe('#getEditionComplexFromRoute()', () => {
+ describe('#updateEditionComplexFromRoute()', () => {
it('... should have been called', () => {
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
});
- it('... should get id from router', () => {
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
+ it('... should trigger `EditionComplexesService.getEditionComplexById`', () => {
+ const getEditionComplexByIdSpy = spyOn(
+ EditionComplexesService,
+ 'getEditionComplexById'
+ ).and.callThrough();
+
+ component.updateEditionComplexFromRoute();
+ fixture.detectChanges();
+
+ expectSpyCall(getEditionComplexByIdSpy, 1);
+ });
+ it('... should get id from router', () => {
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
expectSpyCall(
- editionServiceUpdateEditionComplexSpy,
+ editionServiceUpdateSelectedEditionComplexSpy,
1,
- expectedEditionComplexes[expectedSelectedEditionComplexId]
+ EditionComplexesService.getEditionComplexById(expectedSelectedEditionComplexId)
);
});
- it('... should get correct id from router', () => {
+ it('... should get correct complex from router id', () => {
// Call with op. 12 (default)
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 1, expectedEditionComplexes.OP12);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(
+ editionServiceUpdateSelectedEditionComplexSpy,
+ 1,
+ EditionComplexesService.getEditionComplexById('OP12')
+ );
// ----------------
// Change to op. 25
@@ -146,18 +166,33 @@ describe('EditionComplexComponent (DONE)', () => {
// Trigger initial data binding
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 2, expectedEditionComplexes.OP25);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(
+ editionServiceUpdateSelectedEditionComplexSpy,
+ 2,
+ EditionComplexesService.getEditionComplexById('OP25')
+ );
+ });
+
+ it('... should only get complex from valid router id', () => {
+ expectSpyCall(
+ editionServiceUpdateSelectedEditionComplexSpy,
+ 1,
+ EditionComplexesService.getEditionComplexById('OP12')
+ );
- // ------------------
// Change to non-existing id
mockActivatedRoute.testParamMap = { complexId: 'fail' };
// Trigger initial data binding
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 3, expectedEditionComplexes['fail']);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(
+ editionServiceUpdateSelectedEditionComplexSpy,
+ 1,
+ EditionComplexesService.getEditionComplexById('OP12')
+ );
// ------------------
// Change to empty id
@@ -166,8 +201,12 @@ describe('EditionComplexComponent (DONE)', () => {
// Trigger initial data binding
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 4, expectedEditionComplexes['']);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(
+ editionServiceUpdateSelectedEditionComplexSpy,
+ 1,
+ EditionComplexesService.getEditionComplexById('OP12')
+ );
// ----------------------
// Change to another key
@@ -176,27 +215,31 @@ describe('EditionComplexComponent (DONE)', () => {
// Trigger initial data binding
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 5, expectedEditionComplexes['']);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(
+ editionServiceUpdateSelectedEditionComplexSpy,
+ 1,
+ EditionComplexesService.getEditionComplexById('OP12')
+ );
});
it('... should have updated selectedEditionComplex$ (via EditionService)', () => {
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
expectSpyCall(
- editionServiceUpdateEditionComplexSpy,
+ editionServiceUpdateSelectedEditionComplexSpy,
1,
- expectedEditionComplexes[expectedSelectedEditionComplexId]
+ EditionComplexesService.getEditionComplexById(expectedSelectedEditionComplexId)
);
});
it('... should get edition complex from EditionService and set selectedEditionComplex$', () => {
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
expectSpyCall(
- editionServiceUpdateEditionComplexSpy,
+ editionServiceUpdateSelectedEditionComplexSpy,
1,
- expectedEditionComplexes[expectedSelectedEditionComplexId]
+ EditionComplexesService.getEditionComplexById(expectedSelectedEditionComplexId)
);
- expectSpyCall(editionServiceGetEditionComplexSpy, 1);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 1);
expect(component.selectedEditionComplex$).toBeDefined();
});
@@ -204,13 +247,13 @@ describe('EditionComplexComponent (DONE)', () => {
it('... should get correct edition complex from EditionService when complex id changes', () => {
// ----------------
// Check for op. 12
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
expectSpyCall(
- editionServiceUpdateEditionComplexSpy,
+ editionServiceUpdateSelectedEditionComplexSpy,
1,
- expectedEditionComplexes[expectedSelectedEditionComplexId]
+ EditionComplexesService.getEditionComplexById(expectedSelectedEditionComplexId)
);
- expectSpyCall(editionServiceGetEditionComplexSpy, 1);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 1);
// ----------------
// Change to op. 25
@@ -220,13 +263,13 @@ describe('EditionComplexComponent (DONE)', () => {
// Apply changes
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
expectSpyCall(
- editionServiceUpdateEditionComplexSpy,
+ editionServiceUpdateSelectedEditionComplexSpy,
2,
- expectedEditionComplexes[expectedSelectedEditionComplexId]
+ EditionComplexesService.getEditionComplexById(expectedSelectedEditionComplexId)
);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
expect(component.selectedEditionComplex$).toBeDefined();
});
@@ -235,29 +278,33 @@ describe('EditionComplexComponent (DONE)', () => {
const opusComplex = new EditionComplex(
{
title: 'Test Opus Complex',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
+ catalogueType: 'OPUS',
catalogueNumber: '100',
},
{
editors: [],
lastModified: '---',
},
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
+ { series: '1', section: '5' }
);
expectedSelectedEditionComplexId = 'op100';
- expectedEditionComplexes[expectedSelectedEditionComplexId.toUpperCase()] = opusComplex;
+
+ spyOn(EditionComplexesService, 'getEditionComplexById').and.callFake((id: string) => {
+ if (id.toUpperCase() === expectedSelectedEditionComplexId.toUpperCase()) {
+ return opusComplex;
+ }
+ return null;
+ });
mockActivatedRoute.testParamMap = { complexId: expectedSelectedEditionComplexId };
- editionServiceUpdateEditionComplexSpy.and.callThrough();
+ editionServiceUpdateSelectedEditionComplexSpy.and.callThrough();
// Apply changes
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 2, opusComplex);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(editionServiceUpdateSelectedEditionComplexSpy, 2, opusComplex);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
expect(component.selectedEditionComplex$).toBeDefined();
});
@@ -266,29 +313,34 @@ describe('EditionComplexComponent (DONE)', () => {
const mnrComplex = new EditionComplex(
{
title: 'Test M Complex',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR,
+ catalogueType: 'MNR',
catalogueNumber: '100',
},
{
editors: [],
lastModified: '---',
},
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
+ { series: '1', section: '5' }
);
expectedSelectedEditionComplexId = 'm100';
- expectedEditionComplexes[expectedSelectedEditionComplexId.toUpperCase()] = mnrComplex;
+
+ // Spy on the static method and provide a custom implementation
+ spyOn(EditionComplexesService, 'getEditionComplexById').and.callFake((id: string) => {
+ if (id.toUpperCase() === expectedSelectedEditionComplexId.toUpperCase()) {
+ return mnrComplex;
+ }
+ return null;
+ });
mockActivatedRoute.testParamMap = { complexId: expectedSelectedEditionComplexId };
- editionServiceUpdateEditionComplexSpy.and.callThrough();
+ editionServiceUpdateSelectedEditionComplexSpy.and.callThrough();
// Apply changes
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 2, mnrComplex);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(editionServiceUpdateSelectedEditionComplexSpy, 2, mnrComplex);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
expect(component.selectedEditionComplex$).toBeDefined();
});
@@ -297,29 +349,34 @@ describe('EditionComplexComponent (DONE)', () => {
const mnrPlusComplex = new EditionComplex(
{
title: 'Test M* Complex',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.MNR_PLUS,
+ catalogueType: 'MNR_PLUS',
catalogueNumber: '100',
},
{
editors: [],
lastModified: '---',
},
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
+ { series: '1', section: '5' }
);
expectedSelectedEditionComplexId = 'mPlus100';
- expectedEditionComplexes[expectedSelectedEditionComplexId.toUpperCase()] = mnrPlusComplex;
+
+ // Spy on the static method and provide a custom implementation
+ spyOn(EditionComplexesService, 'getEditionComplexById').and.callFake((id: string) => {
+ if (id.toUpperCase() === expectedSelectedEditionComplexId.toUpperCase()) {
+ return mnrPlusComplex;
+ }
+ return null;
+ });
mockActivatedRoute.testParamMap = { complexId: expectedSelectedEditionComplexId };
- editionServiceUpdateEditionComplexSpy.and.callThrough();
+ editionServiceUpdateSelectedEditionComplexSpy.and.callThrough();
// Apply changes
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 2, mnrPlusComplex);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(editionServiceUpdateSelectedEditionComplexSpy, 2, mnrPlusComplex);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
expect(component.selectedEditionComplex$).toBeDefined();
});
@@ -328,26 +385,31 @@ describe('EditionComplexComponent (DONE)', () => {
const incompleteComplex = new EditionComplex(
{
title: 'Test Incomplete Complex',
- catalogueType: EDITION_CATALOGUE_TYPE_CONSTANTS.OPUS,
+ catalogueType: 'OPUS',
catalogueNumber: '100',
},
null,
- null,
- null,
null
);
expectedSelectedEditionComplexId = 'op100';
- expectedEditionComplexes[expectedSelectedEditionComplexId.toUpperCase()] = incompleteComplex;
+
+ // Spy on the static method and provide a custom implementation
+ spyOn(EditionComplexesService, 'getEditionComplexById').and.callFake((id: string) => {
+ if (id.toUpperCase() === expectedSelectedEditionComplexId.toUpperCase()) {
+ return incompleteComplex;
+ }
+ return null;
+ });
mockActivatedRoute.testParamMap = { complexId: expectedSelectedEditionComplexId };
- editionServiceUpdateEditionComplexSpy.and.callThrough();
+ editionServiceUpdateSelectedEditionComplexSpy.and.callThrough();
// Apply changes
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 2, incompleteComplex);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(editionServiceUpdateSelectedEditionComplexSpy, 2, incompleteComplex);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
expect(component.selectedEditionComplex$).toBeDefined();
});
@@ -359,22 +421,27 @@ describe('EditionComplexComponent (DONE)', () => {
editors: [],
lastModified: '---',
},
- EDITION_ROUTE_CONSTANTS.SERIES_1,
- EDITION_ROUTE_CONSTANTS.SECTION_5,
- EDITION_TYPE_CONSTANTS.SKETCH_EDITION
+ { series: '1', section: '5' }
);
expectedSelectedEditionComplexId = 'op100';
- expectedEditionComplexes[expectedSelectedEditionComplexId.toUpperCase()] = incompleteComplex;
+
+ // Spy on the static method and provide a custom implementation
+ spyOn(EditionComplexesService, 'getEditionComplexById').and.callFake((id: string) => {
+ if (id.toUpperCase() === expectedSelectedEditionComplexId.toUpperCase()) {
+ return incompleteComplex;
+ }
+ return null;
+ });
mockActivatedRoute.testParamMap = { complexId: expectedSelectedEditionComplexId };
- editionServiceUpdateEditionComplexSpy.and.callThrough();
+ editionServiceUpdateSelectedEditionComplexSpy.and.callThrough();
// Apply changes
fixture.detectChanges();
- expectSpyCall(getEditionComplexFromRouteSpy, 1);
- expectSpyCall(editionServiceUpdateEditionComplexSpy, 2, incompleteComplex);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
+ expectSpyCall(updateEditionComplexFromRouteSpy, 1);
+ expectSpyCall(editionServiceUpdateSelectedEditionComplexSpy, 2, incompleteComplex);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
expect(component.selectedEditionComplex$).toBeDefined();
});
@@ -384,7 +451,7 @@ describe('EditionComplexComponent (DONE)', () => {
it('... should have cleared selectedEditionComplex$ on destroy (via EditionService)', () => {
component.ngOnDestroy();
- expectSpyCall(editionServiceClearEditionComplexSpy, 1);
+ expectSpyCall(editionServiceClearSelectedEditionComplexSpy, 1);
});
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.ts
index 25ad7126c..c539be565 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-complex.component.ts
@@ -1,13 +1,12 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
-import { delay, Observable } from 'rxjs';
+import { delay, EMPTY, Observable } from 'rxjs';
-import { UtilityService } from '@awg-app/core/services';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
+import { UtilityService } from '@awg-core/services';
import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import { EditionComplex } from '@awg-views/edition-view/models';
-import { EditionService } from '@awg-views/edition-view/services';
+import { EditionComplexesService, EditionService } from '@awg-views/edition-view/services';
/**
* The EditionComplex component.
@@ -61,21 +60,27 @@ export class EditionComplexComponent implements OnDestroy, OnInit {
* when initializing the component.
*/
ngOnInit(): void {
- this.getEditionComplexFromRoute();
+ this.updateEditionComplexFromRoute();
}
/**
- * Public method: getEditionComplexFromRoute.
+ * Public method: updateEditionComplexFromRoute.
*
- * It subscribes to the route params to get the id of the current edition complex and load it from the edition service.
+ * It fetches the route params to get the id of the current edition complex and updates the edition service.
*
- * @returns {void} Gets the current edition complex from the edition service.
+ * @returns {void} Updates the current edition complex from the route.
*/
- getEditionComplexFromRoute(): void {
+ updateEditionComplexFromRoute(): void {
this.route.paramMap.subscribe(params => {
const id: string = params.get('complexId') || '';
- this.editionService.updateEditionComplex(EDITION_COMPLEXES[id.toUpperCase()]);
- this.selectedEditionComplex$ = this.editionService.getEditionComplex().pipe(delay(0));
+ const complex = EditionComplexesService.getEditionComplexById(id.toUpperCase());
+
+ if (complex) {
+ this.editionService.updateSelectedEditionComplex(complex);
+ this.selectedEditionComplex$ = this.editionService.getSelectedEditionComplex().pipe(delay(0));
+ } else {
+ this.selectedEditionComplex$ = EMPTY;
+ }
});
}
@@ -89,6 +94,6 @@ export class EditionComplexComponent implements OnDestroy, OnInit {
*/
ngOnDestroy() {
// Remove selected edition complex
- this.editionService.clearEditionComplex();
+ this.editionService.clearSelectedEditionComplex();
}
}
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.spec.ts
index 19af11189..a24effeac 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.spec.ts
@@ -7,14 +7,13 @@ import { of as observableOf } from 'rxjs';
import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
-import { expectSpyCall, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import { expectSpyCall, expectToEqual, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
import { RouterOutletStubComponent } from '@testing/router-stubs';
import { RouterLinkButton } from '@awg-shared/router-link-button-group/router-link-button.model';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import { EditionComplex } from '@awg-views/edition-view/models';
-import { EditionService } from '@awg-views/edition-view/services';
+import { EditionComplexesService, EditionService } from '@awg-views/edition-view/services';
import { EditionDetailNavComponent } from './edition-detail-nav.component';
@@ -37,14 +36,14 @@ describe('EditionDetailNavComponent (DONE)', () => {
let expectedEditionComplex: EditionComplex;
let setButtonsSpy: Spy;
- let getEditionComplexSpy: Spy;
+ let getSelectedEditionComplexSpy: Spy;
beforeEach(waitForAsync(() => {
// Create a fake service object with a `getData()` spy
- const mockEditionService = jasmine.createSpyObj('EditionService', ['getEditionComplex']);
+ const mockEditionService = jasmine.createSpyObj('EditionService', ['getSelectedEditionComplex']);
// Make the spy return a synchronous Observable with the test data
- getEditionComplexSpy = mockEditionService.getEditionComplex.and.returnValue(
- observableOf(EDITION_COMPLEXES.OP12)
+ getSelectedEditionComplexSpy = mockEditionService.getSelectedEditionComplex.and.returnValue(
+ observableOf(EditionComplexesService.getEditionComplexById('OP12'))
);
TestBed.configureTestingModule({
@@ -59,7 +58,7 @@ describe('EditionDetailNavComponent (DONE)', () => {
compDe = fixture.debugElement;
// Test data
- expectedEditionComplex = EDITION_COMPLEXES.OP12;
+ expectedEditionComplex = EditionComplexesService.getEditionComplexById('OP12');
expectedEditionRouterLinkButtons = [
new RouterLinkButton(
expectedEditionComplex.baseRoute,
@@ -116,7 +115,7 @@ describe('EditionDetailNavComponent (DONE)', () => {
});
it('... should not have been called', () => {
- expectSpyCall(getEditionComplexSpy, 0);
+ expectSpyCall(getSelectedEditionComplexSpy, 0);
});
});
@@ -149,15 +148,12 @@ describe('EditionDetailNavComponent (DONE)', () => {
describe('#getEditionComplex()', () => {
it('... should have been called', () => {
- expectSpyCall(getEditionComplexSpy, 1);
+ expectSpyCall(getSelectedEditionComplexSpy, 1);
});
});
it('... should have `editionComplex`', () => {
- expect(component.editionComplex).withContext('should be defined').toBeDefined();
- expect(component.editionComplex)
- .withContext(`should equal ${expectedEditionComplex}`)
- .toEqual(expectedEditionComplex);
+ expectToEqual(component.editionComplex, expectedEditionComplex);
});
describe('#setButtons()', () => {
@@ -166,10 +162,7 @@ describe('EditionDetailNavComponent (DONE)', () => {
});
it('... should have `editionRouterLinkButtons`', () => {
- expect(component.editionRouterLinkButtons).toBeDefined();
- expect(component.editionRouterLinkButtons)
- .withContext(`should equal ${expectedEditionRouterLinkButtons}`)
- .toEqual(expectedEditionRouterLinkButtons);
+ expectToEqual(component.editionRouterLinkButtons, expectedEditionRouterLinkButtons);
});
});
@@ -188,10 +181,7 @@ describe('EditionDetailNavComponent (DONE)', () => {
RouterLinkButtonGroupStubComponent
) as RouterLinkButtonGroupStubComponent;
- expect(buttonCmp.routerLinkButtons).toBeTruthy();
- expect(buttonCmp.routerLinkButtons)
- .withContext(`should equal ${expectedEditionRouterLinkButtons}`)
- .toEqual(expectedEditionRouterLinkButtons);
+ expectToEqual(buttonCmp.routerLinkButtons, expectedEditionRouterLinkButtons);
});
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.ts
index effd1337f..4b08a6d98 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-detail-nav/edition-detail-nav.component.ts
@@ -71,7 +71,7 @@ export class EditionDetailNavComponent implements OnInit, OnDestroy {
*/
getEditionComplex(): void {
this.editionService
- .getEditionComplex()
+ .getSelectedEditionComplex()
.pipe(takeUntil(this._destroyed$))
.subscribe({
next: (complex: EditionComplex) => {
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.html
index 2043724b5..6f275d199 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.html
@@ -32,8 +32,9 @@
erscheinen im Zusammenhang
der vollständigen Edition von
in
- {{ editionRouteConstants.EDITION.short }} {{ editionComplex.series.short }}/{{
- editionComplex.section.short
+ {{ editionRouteConstants.EDITION.short }}
+ {{ editionComplex.pubStatement.series.short }}/{{
+ editionComplex.pubStatement.section.short
}}.]
@@ -96,23 +97,12 @@ Statischer Graph
}
} @else {
+
@if (errorObject) {
-
-
-
{{ errorObject | json }}
-
-
+
+ } @else {
+
+
}
}
-
-
-
- @if (errorObject) {
-
-
-
{{ errorObject | json }}
-
-
- }
-
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.spec.ts
index 2b69bed28..893a2e870 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.spec.ts
@@ -2,7 +2,14 @@ import { DOCUMENT, JsonPipe } from '@angular/common';
import { Component, DebugElement, Input } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
-import { EmptyError, lastValueFrom, Observable, of as observableOf, throwError as observableThrowError } from 'rxjs';
+import {
+ EMPTY,
+ EmptyError,
+ lastValueFrom,
+ Observable,
+ of as observableOf,
+ throwError as observableThrowError,
+} from 'rxjs';
import Spy = jasmine.Spy;
import { FontAwesomeTestingModule } from '@fortawesome/angular-fontawesome/testing';
@@ -21,14 +28,20 @@ import {
import { mockEditionData } from '@testing/mock-data';
import { CompileHtmlComponent } from '@awg-shared/compile-html';
-import { EDITION_COMPLEXES, EDITION_GRAPH_IMAGES_DATA } from '@awg-views/edition-view/data';
+import { EDITION_GRAPH_IMAGES_DATA } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import { EditionComplex, Graph, GraphList, GraphRDFData, GraphSparqlQuery } from '@awg-views/edition-view/models';
-import { EditionDataService, EditionService } from '@awg-views/edition-view/services';
+import { EditionComplexesService, EditionDataService, EditionService } from '@awg-views/edition-view/services';
import { EditionGraphComponent } from './edition-graph.component';
// Mock components
+@Component({ selector: 'awg-error-alert', template: '' })
+class ErrorAlertStubComponent {
+ @Input()
+ errorObject: any;
+}
+
@Component({ selector: 'awg-graph-visualizer', template: '' })
class GraphVisualizerStubComponent {
@Input()
@@ -46,6 +59,9 @@ class ModalStubComponent {
}
}
+@Component({ selector: 'awg-twelve-tone-spinner', template: '' })
+class TwelveToneSpinnerStubComponent {}
+
describe('EditionGraphComponent (DONE)', () => {
let component: EditionGraphComponent;
let fixture: ComponentFixture
;
@@ -61,9 +77,7 @@ describe('EditionGraphComponent (DONE)', () => {
let modalOpenSpy: Spy;
let compGetEditonGraphDataSpy: Spy;
let editionDataServiceGetEditionGraphDataSpy: Spy;
- let editionServiceGetEditionComplexSpy: Spy;
-
- const jsonPipe = new JsonPipe();
+ let editionServiceGetSelectedEditionComplexSpy: Spy;
let expectedEditionComplex: EditionComplex;
let expectedEditionGraphDataEmpty: GraphList;
@@ -72,6 +86,12 @@ describe('EditionGraphComponent (DONE)', () => {
let expectedIsFullscreen: boolean;
+ const jsonPipe = new JsonPipe();
+
+ beforeAll(() => {
+ EditionComplexesService.initializeEditionComplexesList();
+ });
+
beforeEach(waitForAsync(() => {
// Mocked editionDataService
mockEditionDataService = {
@@ -80,16 +100,18 @@ describe('EditionGraphComponent (DONE)', () => {
};
// Mocked editionService
mockEditionService = {
- getEditionComplex: (): Observable => observableOf(expectedEditionComplex),
+ getSelectedEditionComplex: (): Observable => observableOf(expectedEditionComplex),
};
TestBed.configureTestingModule({
imports: [FontAwesomeTestingModule],
declarations: [
EditionGraphComponent,
+ ErrorAlertStubComponent,
GraphVisualizerStubComponent,
ModalStubComponent,
CompileHtmlComponent,
+ TwelveToneSpinnerStubComponent,
],
providers: [
{ provide: EditionDataService, useValue: mockEditionDataService },
@@ -112,7 +134,7 @@ describe('EditionGraphComponent (DONE)', () => {
// TestData (default)
expectedIsFullscreen = false;
- expectedEditionComplex = EDITION_COMPLEXES.OP12;
+ expectedEditionComplex = EditionComplexesService.getEditionComplexById('OP12');
expectedEditionGraphDataEmpty = JSON.parse(JSON.stringify(mockEditionData.mockGraphEmptyData));
@@ -125,14 +147,17 @@ describe('EditionGraphComponent (DONE)', () => {
// Spies on component methods
compGetEditonGraphDataSpy = spyOn(component, 'getEditionGraphData').and.callThrough();
- editionServiceGetEditionComplexSpy = spyOn(editionService, 'getEditionComplex').and.callThrough();
+ editionServiceGetSelectedEditionComplexSpy = spyOn(
+ editionService,
+ 'getSelectedEditionComplex'
+ ).and.callThrough();
editionDataServiceGetEditionGraphDataSpy = spyOn(editionDataService, 'getEditionGraphData').and.callFake(
(editionComplex: EditionComplex) => {
switch (editionComplex) {
- case EDITION_COMPLEXES.OP12: {
+ case EditionComplexesService.getEditionComplexById('OP12'): {
return observableOf(expectedEditionGraphDataEmpty);
}
- case EDITION_COMPLEXES.OP25: {
+ case EditionComplexesService.getEditionComplexById('OP25'): {
return observableOf(expectedEditionGraphDataOp25);
}
default: {
@@ -152,11 +177,11 @@ describe('EditionGraphComponent (DONE)', () => {
});
it('... injected editionService should use provided mockValue', () => {
- expect(mockEditionService === editionService).toBe(true);
+ expectToBe(mockEditionService === editionService, true);
});
it('... injected editionDataService should use provided mockValue', () => {
- expect(mockEditionDataService === editionDataService).toBe(true);
+ expectToBe(mockEditionDataService === editionDataService, true);
});
describe('BEFORE initial data binding', () => {
@@ -172,7 +197,7 @@ describe('EditionGraphComponent (DONE)', () => {
});
it('... should have `errorObject` = null', () => {
- expect(component.errorObject).toBeNull();
+ expectToBe(component.errorObject, null);
});
it('... should have `isFullscreen`', () => {
@@ -192,7 +217,7 @@ describe('EditionGraphComponent (DONE)', () => {
});
describe('VIEW', () => {
- it('... should have a `div`', () => {
+ it('... should contain a `div`', () => {
getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
});
@@ -202,19 +227,29 @@ describe('EditionGraphComponent (DONE)', () => {
getAndExpectDebugElementByDirective(divDes[0], ModalStubComponent, 1, 1);
});
- it('... should not have a nested div.awg-graph-view', () => {
+ it('... should contain no div.awg-graph-view yet', () => {
getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view', 0, 0);
});
- it('... should not have a nested div.errorMessage', () => {
- getAndExpectDebugElementByCss(compDe, 'div.errorMessage', 0, 0);
+ it('... should not contain an error alert component (stubbed)', () => {
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], ErrorAlertStubComponent, 0, 0);
+ });
+
+ it('... should not contain a loading spinner component (stubbed)', () => {
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], TwelveToneSpinnerStubComponent, 0, 0);
});
});
});
describe('AFTER initial data binding', () => {
beforeEach(() => {
- editionServiceGetEditionComplexSpy.and.returnValue(observableOf(EDITION_COMPLEXES.OP12));
+ editionServiceGetSelectedEditionComplexSpy.and.returnValue(
+ observableOf(EditionComplexesService.getEditionComplexById('OP12'))
+ );
// Trigger initial data binding
fixture.detectChanges();
@@ -225,11 +260,11 @@ describe('EditionGraphComponent (DONE)', () => {
});
describe('VIEW', () => {
- it('... should have one div.awg-graph-view', () => {
+ it('... should contain one div.awg-graph-view', () => {
getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view', 1, 1);
});
- it('... should not contain a div.awg-graph-view if graph data is not provided', waitForAsync(() => {
+ it('... should not contain a div in div.awg-graph-view if graph data is not provided', waitForAsync(() => {
const noGraphData = new GraphList();
noGraphData.graph = undefined;
@@ -241,7 +276,7 @@ describe('EditionGraphComponent (DONE)', () => {
getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view > div', 0, 0);
}));
- it('... should contain a div.awg-graph-view if graph data is provided', () => {
+ it('... should contain a div in div.awg-graph-view if graph data is provided', () => {
getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view > div', 1, 1);
});
@@ -301,7 +336,11 @@ describe('EditionGraphComponent (DONE)', () => {
const shortComplexSpan = mockDocument.createElement('span');
shortComplexSpan.innerHTML = expectedEditionComplex.complexId.short;
- const graphPlaceholder = `[Die Graph-Visualisierungen zum Editionskomplex ${fullComplexSpan.textContent} erscheinen im Zusammenhang der vollständigen Edition von ${shortComplexSpan.textContent} in ${expectedEditionRouteConstants.EDITION.short} ${expectedEditionComplex.series.short}/${expectedEditionComplex.section.short}.]`;
+ const awg = EDITION_ROUTE_CONSTANTS.EDITION.short;
+ const series = expectedEditionComplex.pubStatement.series.short;
+ const section = expectedEditionComplex.pubStatement.section.short;
+
+ const graphPlaceholder = `[Die Graph-Visualisierungen zum Editionskomplex ${fullComplexSpan.textContent} erscheinen im Zusammenhang der vollständigen Edition von ${shortComplexSpan.textContent} in ${awg} ${series}/${section}.]`;
expectToBe(pEl.textContent.trim(), graphPlaceholder);
}));
@@ -546,20 +585,56 @@ describe('EditionGraphComponent (DONE)', () => {
detectChangesOnPush(fixture);
}));
- it('... should not have graph view, but one div.errorMessage with centered danger alert', waitForAsync(() => {
+ it('... should not contain graph view, but one ErrorAlertComponent (stubbed)', waitForAsync(() => {
getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view', 0, 0);
- const errorDes = getAndExpectDebugElementByCss(compDe, 'div.errorMessage', 1, 1);
- getAndExpectDebugElementByCss(errorDes[0], 'div.text-center > div.alert-danger', 1, 1);
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+ getAndExpectDebugElementByDirective(divDes[0], ErrorAlertStubComponent, 1, 1);
}));
- it('... should display errorMessage', waitForAsync(() => {
- const alertDes = getAndExpectDebugElementByCss(compDe, 'div.alert-danger', 1, 1);
- const alertEl = alertDes[0].nativeElement;
+ it('... should pass down error object to ErrorAlertComponent', waitForAsync(() => {
+ const errorAlertDes = getAndExpectDebugElementByDirective(compDe, ErrorAlertStubComponent, 1, 1);
+ const errorAlertCmp = errorAlertDes[0].injector.get(
+ ErrorAlertStubComponent
+ ) as ErrorAlertStubComponent;
- expectToContain(alertEl.textContent, jsonPipe.transform(expectedError));
+ expectToEqual(errorAlertCmp.errorObject, expectedError);
}));
});
+
+ describe('on loading', () => {
+ describe('... should contain only TwelveToneSpinnerComponent (stubbed) if ... ', () => {
+ it('... editionGraphData$ is EMPTY', () => {
+ // Mock empty observable
+ component.editionGraphData$ = EMPTY;
+ detectChangesOnPush(fixture);
+
+ getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view', 0, 0);
+ getAndExpectDebugElementByDirective(compDe, ErrorAlertStubComponent, 0, 0);
+ getAndExpectDebugElementByDirective(compDe, TwelveToneSpinnerStubComponent, 1, 1);
+ });
+
+ it('... editionGraphData$ is undefined', () => {
+ // Mock undefined response
+ component.editionGraphData$ = observableOf(undefined);
+ detectChangesOnPush(fixture);
+
+ getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view', 0, 0);
+ getAndExpectDebugElementByDirective(compDe, ErrorAlertStubComponent, 0, 0);
+ getAndExpectDebugElementByDirective(compDe, TwelveToneSpinnerStubComponent, 1, 1);
+ });
+
+ it('... editionGraphData$ is null', () => {
+ // Mock null response
+ component.editionGraphData$ = observableOf(null);
+ detectChangesOnPush(fixture);
+
+ getAndExpectDebugElementByCss(compDe, 'div.awg-graph-view', 0, 0);
+ getAndExpectDebugElementByDirective(compDe, ErrorAlertStubComponent, 0, 0);
+ getAndExpectDebugElementByDirective(compDe, TwelveToneSpinnerStubComponent, 1, 1);
+ });
+ });
+ });
});
describe('#getEditionGraphData()', () => {
@@ -567,12 +642,12 @@ describe('EditionGraphComponent (DONE)', () => {
expect(component.getEditionGraphData).toBeDefined();
});
- it('... should trigger editionService.getEditionComplex', () => {
- expectSpyCall(editionServiceGetEditionComplexSpy, 1);
+ it('... should trigger editionService.getSelectedEditionComplex', () => {
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 1);
});
it('... should get current editionComplex from editionService', () => {
- expectSpyCall(editionServiceGetEditionComplexSpy, 1);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 1);
expectToEqual(component.editionComplex, expectedEditionComplex);
});
@@ -580,14 +655,16 @@ describe('EditionGraphComponent (DONE)', () => {
it('... should update editionComplex when editionService emits changed value', waitForAsync(() => {
// ----------------
// Change to op. 25
- editionServiceGetEditionComplexSpy.and.returnValue(observableOf(EDITION_COMPLEXES.OP25));
+ editionServiceGetSelectedEditionComplexSpy.and.returnValue(
+ observableOf(EditionComplexesService.getEditionComplexById('OP25'))
+ );
component.getEditionGraphData();
detectChangesOnPush(fixture);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
- expectToEqual(component.editionComplex, EDITION_COMPLEXES.OP25);
+ expectToEqual(component.editionComplex, EditionComplexesService.getEditionComplexById('OP25'));
}));
it('... should trigger editionDataService.getEditionGraph', () => {
@@ -601,14 +678,19 @@ describe('EditionGraphComponent (DONE)', () => {
it('... should re-trigger editionDataService.getEditionGraph with updated editionComplex', waitForAsync(() => {
// ----------------
// Change to op. 25
- // ExpectedEditionComplex = EDITION_COMPLEXES.op25;
- editionServiceGetEditionComplexSpy.and.returnValue(observableOf(EDITION_COMPLEXES.OP25));
+ editionServiceGetSelectedEditionComplexSpy.and.returnValue(
+ observableOf(EditionComplexesService.getEditionComplexById('OP25'))
+ );
component.getEditionGraphData();
detectChangesOnPush(fixture);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
- expectSpyCall(editionDataServiceGetEditionGraphDataSpy, 2, EDITION_COMPLEXES.OP25);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
+ expectSpyCall(
+ editionDataServiceGetEditionGraphDataSpy,
+ 2,
+ EditionComplexesService.getEditionComplexById('OP25')
+ );
}));
it('... should get editionGraphData from editionDataService and set editionGraphData$', waitForAsync(() => {
@@ -618,9 +700,7 @@ describe('EditionGraphComponent (DONE)', () => {
detectChangesOnPush(fixture);
expectAsync(lastValueFrom(component.editionGraphData$)).toBeResolved();
- expectAsync(lastValueFrom(component.editionGraphData$))
- .withContext(`should be resolved to ${expectedEditionGraphDataEmpty}`)
- .toBeResolvedTo(expectedEditionGraphDataEmpty);
+ expectAsync(lastValueFrom(component.editionGraphData$)).toBeResolvedTo(expectedEditionGraphDataEmpty);
}));
it('... should update editionGraphData$ when editionService emits changed value', waitForAsync(() => {
@@ -628,19 +708,22 @@ describe('EditionGraphComponent (DONE)', () => {
// ----------------
// Change to op. 25
- // ExpectedEditionComplex = EDITION_COMPLEXES.op25;
- editionServiceGetEditionComplexSpy.and.returnValue(observableOf(EDITION_COMPLEXES.OP25));
+ editionServiceGetSelectedEditionComplexSpy.and.returnValue(
+ observableOf(EditionComplexesService.getEditionComplexById('OP25'))
+ );
component.getEditionGraphData();
detectChangesOnPush(fixture);
- expectSpyCall(editionServiceGetEditionComplexSpy, 2);
- expectSpyCall(editionDataServiceGetEditionGraphDataSpy, 2, EDITION_COMPLEXES.OP25);
+ expectSpyCall(editionServiceGetSelectedEditionComplexSpy, 2);
+ expectSpyCall(
+ editionDataServiceGetEditionGraphDataSpy,
+ 2,
+ EditionComplexesService.getEditionComplexById('OP25')
+ );
expectAsync(lastValueFrom(component.editionGraphData$)).toBeResolved();
- expectAsync(lastValueFrom(component.editionGraphData$))
- .withContext(`should be resolved to ${expectedEditionGraphDataOp25}`)
- .toBeResolvedTo(expectedEditionGraphDataOp25);
+ expectAsync(lastValueFrom(component.editionGraphData$)).toBeResolvedTo(expectedEditionGraphDataOp25);
}));
it('... should return empty observable and set errorObject if switchMap fails', waitForAsync(() => {
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.ts
index 78035a336..ad9fe9e97 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/edition-graph.component.ts
@@ -165,7 +165,7 @@ export class EditionGraphComponent implements OnInit {
getEditionGraphData(): void {
this.editionGraphData$ = this.editionService
// Get current editionComplex from editionService
- .getEditionComplex()
+ .getSelectedEditionComplex()
.pipe(
switchMap((complex: EditionComplex) => {
// Set current editionComplex
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/force-graph/force-graph.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/force-graph/force-graph.component.ts
index 2f4863702..141dc53bd 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/force-graph/force-graph.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/force-graph/force-graph.component.ts
@@ -424,28 +424,12 @@ export class ForceGraphComponent implements OnInit, OnChanges, OnDestroy {
* @returns {void} Attaches the data and sets up the simulation.
*/
private _attachData(): void {
- // Limit result length
const triples: Triple[] = this.graphVisualizerService.limitTriples(this.currentQueryResultTriples, this.limit);
- // If type of triples is text/turtle (not array)
- // The triples must be parsed to objects instead
- if (typeof triples === 'string') {
- this.graphVisualizerService.parseTripleString(triples).then((data: { triples; namespaces }) => {
- const abrTriples: Triple[] = this.graphVisualizerService.abbreviateTriples(
- data.triples,
- data.namespaces
- );
- this._simulationData = this._triplesToD3GraphData(abrTriples);
-
- this._setupForceSimulation();
- this._updateSVG();
- });
- } else {
- this._simulationData = this._triplesToD3GraphData(triples);
+ this._simulationData = this._triplesToD3GraphData(triples);
- this._setupForceSimulation();
- this._updateSVG();
- }
+ this._setupForceSimulation();
+ this._updateSVG();
}
/**
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.html
index 0c4d0d76f..e2169e361 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.html
@@ -50,10 +50,6 @@
[isFullscreen]="isFullscreen">
}
}
-
-
-
-
}
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.spec.ts
index 795c430ac..ef2bb2b90 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.spec.ts
@@ -8,6 +8,8 @@ import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
import {
expectSpyCall,
+ expectToBe,
+ expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
} from '@testing/expect-helper';
@@ -226,8 +228,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
});
it('... should have defaultForceGraphHeight ', () => {
- expect(component.defaultForceGraphHeight).toBeTruthy();
- expect(component.defaultForceGraphHeight).withContext('should be 500').toBe(500);
+ expectToBe(component.defaultForceGraphHeight, 500);
});
it('... should not have triggered `resetTriples()`', () => {
@@ -264,43 +265,30 @@ describe('GraphVisualizerComponent (DONE)', () => {
});
it('... should have graphRDFInputData', () => {
- expect(component.graphRDFInputData).toBeDefined();
- expect(component.graphRDFInputData)
- .withContext(`should equal ${expectedGraphRDFData}`)
- .toEqual(expectedGraphRDFData);
+ expectToEqual(component.graphRDFInputData, expectedGraphRDFData);
});
it('... should have `isFullScreen` input', () => {
- expect(component.isFullscreen).toBeDefined();
- expect(component.isFullscreen).withContext(`should be ${expectedIsFullscreen}`).toBe(expectedIsFullscreen);
+ expectToBe(component.isFullscreen, expectedIsFullscreen);
});
it('... should have triples', () => {
- expect(component.triples).toBeDefined();
- expect(component.triples)
- .withContext(`should equal ${expectedGraphRDFData.triples}`)
- .toEqual(expectedGraphRDFData.triples);
+ expectToEqual(component.triples, expectedGraphRDFData.triples);
});
it('... should have queryList', () => {
- expect(component.queryList).toBeDefined();
- expect(component.queryList)
- .withContext(`should equal ${expectedGraphRDFData.triples}`)
- .toEqual(expectedGraphRDFData.queryList);
+ expectToEqual(component.queryList, expectedGraphRDFData.queryList);
});
it('... should have query', () => {
- expect(component.query).toBeDefined();
- expect(component.query)
- .withContext(`should equal ${expectedGraphRDFData.triples}`)
- .toEqual(expectedGraphRDFData.queryList[0]);
+ expectToEqual(component.query, expectedGraphRDFData.queryList[0]);
});
it('... should have queryResult', () => {
expect(component.queryResult$).toBeDefined();
+
component.queryResult$.subscribe(result => {
- expect(result).toBeTruthy();
- expect(result).withContext(`should equal ${expectedResult}`).toEqual(expectedResult);
+ expectToEqual(result, expectedResult);
});
});
@@ -338,10 +326,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
it('... should set initial triples', () => {
expectSpyCall(resetTriplesSpy, 1, undefined);
- expect(component.triples).toBeDefined();
- expect(component.triples)
- .withContext(`should equal ${expectedGraphRDFData.triples}`)
- .toEqual(expectedGraphRDFData.triples);
+ expectToEqual(component.triples, expectedGraphRDFData.triples);
});
it('... should reset changed triples to initial triples', () => {
@@ -354,8 +339,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
// Wait for fixture to be stable
fixture.detectChanges();
- expect(component.triples).toBeDefined();
- expect(component.triples).withContext(`should equal ${changedTriples}`).toEqual(changedTriples);
+ expectToEqual(component.triples, changedTriples);
// Reset triples
component.resetTriples();
@@ -363,9 +347,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(resetTriplesSpy, 2, undefined);
expect(component.triples).toBeDefined();
- expect(component.triples)
- .withContext(`should equal ${expectedGraphRDFData.triples}`)
- .toEqual(expectedGraphRDFData.triples);
+ expectToEqual(component.triples, expectedGraphRDFData.triples);
});
it('... should not do anything if no triples are provided from rdf data', () => {
@@ -405,19 +387,13 @@ describe('GraphVisualizerComponent (DONE)', () => {
it('... should set initial queryList', () => {
expectSpyCall(resetQuerySpy, 1, undefined);
- expect(component.queryList).toBeDefined();
- expect(component.queryList)
- .withContext(`should equal ${expectedGraphRDFData.queryList}`)
- .toEqual(expectedGraphRDFData.queryList);
+ expectToEqual(component.queryList, expectedGraphRDFData.queryList);
});
it('... should set initial query', () => {
expectSpyCall(resetQuerySpy, 1, undefined);
- expect(component.query).toBeDefined();
- expect(component.query)
- .withContext(`should equal ${expectedGraphRDFData.queryList[0]}`)
- .toEqual(expectedGraphRDFData.queryList[0]);
+ expectToEqual(component.query, expectedGraphRDFData.queryList[0]);
});
it('... should find and reset a query from queryList if queryLabel and queryType is known', () => {
@@ -432,18 +408,9 @@ describe('GraphVisualizerComponent (DONE)', () => {
// Matches queryList queries by label
expectSpyCall(resetQuerySpy, 2, undefined);
- expect(component.query).toBeDefined();
- expect(component.query).withContext(`should equal ${changedQuery}`).toEqual(changedQuery);
-
- expect(component.query.queryLabel).toBeDefined();
- expect(component.query.queryLabel)
- .withContext(`should equal ${changedQuery.queryLabel}`)
- .toEqual(changedQuery.queryLabel);
-
- expect(component.query.queryType).toBeDefined();
- expect(component.query.queryType)
- .withContext(`should equal ${changedQuery.queryType}`)
- .toEqual(changedQuery.queryType);
+ expectToEqual(component.query, changedQuery);
+ expectToBe(component.query.queryLabel, changedQuery.queryLabel);
+ expectToBe(component.query.queryType, changedQuery.queryType);
});
describe('... should set query as is, and not find from queryList, if', () => {
@@ -463,18 +430,9 @@ describe('GraphVisualizerComponent (DONE)', () => {
// Matches queryList queries only by label
expectSpyCall(resetQuerySpy, 2, undefined);
- expect(component.query).toBeDefined();
- expect(component.query).withContext(`should equal ${changedQuery}`).toEqual(changedQuery);
-
- expect(component.query.queryLabel).toBeDefined();
- expect(component.query.queryLabel)
- .withContext(`should equal ${changedQuery.queryLabel}`)
- .toBe(changedQuery.queryLabel);
-
- expect(component.query.queryType).toBeDefined();
- expect(component.query.queryType)
- .withContext(`should equal ${changedQuery.queryType}`)
- .toBe(changedQuery.queryType);
+ expectToEqual(component.query, changedQuery);
+ expectToBe(component.query.queryLabel, changedQuery.queryLabel);
+ expectToBe(component.query.queryType, changedQuery.queryType);
});
it('... only queryType is known but not queryLabel', () => {
@@ -490,18 +448,9 @@ describe('GraphVisualizerComponent (DONE)', () => {
// Matches queryList queries only by type
expectSpyCall(resetQuerySpy, 2, undefined);
- expect(component.query).toBeDefined();
- expect(component.query).withContext(`should equal ${changedQuery}`).toEqual(changedQuery);
-
- expect(component.query.queryLabel).toBeDefined();
- expect(component.query.queryLabel)
- .withContext(`should equal ${changedQuery.queryLabel}`)
- .toBe(changedQuery.queryLabel);
-
- expect(component.query.queryType).toBeDefined();
- expect(component.query.queryType)
- .withContext(`should equal ${changedQuery.queryType}`)
- .toBe(changedQuery.queryType);
+ expectToEqual(component.query, changedQuery);
+ expectToBe(component.query.queryLabel, changedQuery.queryLabel);
+ expectToBe(component.query.queryType, changedQuery.queryType);
});
it('... given query is not in queryList', () => {
@@ -521,18 +470,9 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(resetQuerySpy, 2, undefined);
- expect(component.query).toBeDefined();
- expect(component.query).withContext(`should equal ${changedQuery}`).toEqual(changedQuery);
-
- expect(component.query.queryLabel).toBeDefined();
- expect(component.query.queryLabel)
- .withContext(`should equal ${changedQuery.queryLabel}`)
- .toBe(changedQuery.queryLabel);
-
- expect(component.query.queryType).toBeDefined();
- expect(component.query.queryType)
- .withContext(`should equal ${changedQuery.queryType}`)
- .toBe(changedQuery.queryType);
+ expectToEqual(component.query, changedQuery);
+ expectToBe(component.query.queryLabel, changedQuery.queryLabel);
+ expectToBe(component.query.queryType, changedQuery.queryType);
});
});
@@ -544,8 +484,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
component.query = changedQuery;
fixture.detectChanges();
- expect(component.query).toBeDefined();
- expect(component.query).withContext(`should equal ${changedQuery}`).toEqual(changedQuery);
+ expectToEqual(component.query, changedQuery);
// Reset triples
component.resetQuery();
@@ -553,10 +492,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(resetQuerySpy, 2, undefined);
- expect(component.query).toBeDefined();
- expect(component.query)
- .withContext(`should equal ${expectedGraphRDFData.queryList[0]}`)
- .toEqual(expectedGraphRDFData.queryList[0]);
+ expectToEqual(component.query, expectedGraphRDFData.queryList[0]);
});
it('... should not do anything if no queryList is provided from RDF data', () => {
@@ -645,10 +581,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(performQuerySpy, 2, undefined);
expectSpyCall(namespaceSpy, 1, [queryStringWithoutPrefixes, expectedGraphRDFData.triples]);
- expect(component.query).toBeDefined();
- expect(component.query)
- .withContext(`should equal ${expectedGraphRDFData.queryList[0]}`)
- .toEqual(expectedGraphRDFData.queryList[0]);
+ expectToEqual(component.query, expectedGraphRDFData.queryList[0]);
});
it('... should get queryType from service', () => {
@@ -670,8 +603,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectedGraphRDFData.queryList[0].queryString
);
- expect(component.query.queryType).toBeDefined();
- expect(component.query.queryType).withContext('should equal construct').toEqual('construct');
+ expectToBe(component.query.queryType, 'construct');
});
it('... should trigger `_queryLocalStore` for construct queries', () => {
@@ -716,10 +648,9 @@ describe('GraphVisualizerComponent (DONE)', () => {
component.performQuery();
detectChangesOnPush(fixture);
+ expectToBe(component.query.queryType, 'construct');
expectAsync(lastValueFrom(component.queryResult$)).toBeResolved();
- expectAsync(lastValueFrom(component.queryResult$))
- .withContext(`should be resolved to ${expectedResult}`)
- .toBeResolvedTo(expectedResult);
+ expectAsync(lastValueFrom(component.queryResult$)).toBeResolvedTo(expectedResult);
}));
it('... should get queryResult for select queries', waitForAsync(() => {
@@ -730,10 +661,9 @@ describe('GraphVisualizerComponent (DONE)', () => {
component.performQuery();
detectChangesOnPush(fixture);
+ expectToBe(component.query.queryType, 'select');
expectAsync(lastValueFrom(component.queryResult$)).toBeResolved();
- expectAsync(lastValueFrom(component.queryResult$))
- .withContext(`should be resolved to ${expectedResult}`)
- .toBeResolvedTo(expectedResult);
+ expectAsync(lastValueFrom(component.queryResult$)).toBeResolvedTo(expectedResult);
}));
it('... should set empty observable for update query types', waitForAsync(() => {
@@ -743,7 +673,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
component.performQuery();
fixture.detectChanges();
- expect(component.query.queryType).withContext('should be other').toBe('update');
+ expectToBe(component.query.queryType, 'update');
expectAsync(lastValueFrom(component.queryResult$)).toBeRejected();
expectAsync(lastValueFrom(component.queryResult$)).toBeRejectedWithError(EmptyError);
}));
@@ -755,7 +685,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
component.performQuery();
fixture.detectChanges();
- expect(component.query.queryType).withContext('should be other').toBe('other');
+ expectToBe(component.query.queryType, 'other');
expectAsync(lastValueFrom(component.queryResult$)).toBeRejected();
expectAsync(lastValueFrom(component.queryResult$)).toBeRejectedWithError(EmptyError);
}));
@@ -806,14 +736,10 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectAsync(
graphVisualizerService.doQuery(expectedCallback[0], expectedCallback[1], expectedCallback[2])
- )
- .withContext(`should be resolved to ${expectedResult}`)
- .toBeResolvedTo(expectedResult);
+ ).toBeResolvedTo(expectedResult);
expectAsync(lastValueFrom(component.queryResult$)).toBeResolved();
- expectAsync(lastValueFrom(component.queryResult$))
- .withContext(`should be resolved to ${expectedResult}`)
- .toBeResolvedTo(expectedResult);
+ expectAsync(lastValueFrom(component.queryResult$)).toBeResolvedTo(expectedResult);
}));
it('... should return empty array on error', waitForAsync(() => {
@@ -836,9 +762,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
).toBeRejectedWith(expectedError);
expectAsync(lastValueFrom(component.queryResult$)).toBeResolved();
- expectAsync(lastValueFrom(component.queryResult$))
- .withContext(`should be resolved to []`)
- .toBeResolvedTo([]);
+ expectAsync(lastValueFrom(component.queryResult$)).toBeResolvedTo([]);
}));
it('... should log an error on error', async () => {
@@ -885,11 +809,9 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(showErrorMessageSpy, 1);
expect(showErrorMessageSpy.calls.any()).toBeTruthy();
- expect(showErrorMessageSpy.calls.count()).withContext(`should be 1`).toBe(1);
- expect(showErrorMessageSpy.calls.first().args)
- .withContext(`should equal ${expectedToastMessage}`)
- .toEqual([expectedToastMessage]);
- expect(showErrorMessageSpy.calls.allArgs()[0]).withContext(`should equal ${expectedToastMessage}`);
+ expectToBe(showErrorMessageSpy.calls.count(), 1);
+ expectToEqual(showErrorMessageSpy.calls.first().args, [expectedToastMessage]);
+ expectToEqual(showErrorMessageSpy.calls.allArgs()[0], [expectedToastMessage]);
});
it('... should trigger `showErrorMessage` 2x if error message contains `undefined`', async () => {
@@ -916,19 +838,11 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(showErrorMessageSpy, 2);
expect(showErrorMessageSpy.calls.any()).toBeTruthy();
- expect(showErrorMessageSpy.calls.count()).withContext(`should be 2`).toBe(2);
- expect(showErrorMessageSpy.calls.first().args)
- .withContext(`should equal ${expectedToastMessage1}`)
- .toEqual([expectedToastMessage1]);
- expect(showErrorMessageSpy.calls.allArgs()[0])
- .withContext(`should equal ${expectedToastMessage1}`)
- .toEqual([expectedToastMessage1]);
- expect(showErrorMessageSpy.calls.allArgs()[1])
- .withContext(`should equal ${expectedToastMessage2}`)
- .toEqual([expectedToastMessage2]);
- expect(showErrorMessageSpy.calls.mostRecent().args)
- .withContext(`should equal ${expectedToastMessage2}`)
- .toEqual([expectedToastMessage2]);
+ expectToBe(showErrorMessageSpy.calls.count(), 2);
+ expectToEqual(showErrorMessageSpy.calls.first().args, [expectedToastMessage1]);
+ expectToEqual(showErrorMessageSpy.calls.allArgs()[0], [expectedToastMessage1]);
+ expectToEqual(showErrorMessageSpy.calls.allArgs()[1], [expectedToastMessage2]);
+ expectToEqual(showErrorMessageSpy.calls.mostRecent().args, [expectedToastMessage2]);
});
});
@@ -1011,8 +925,8 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(toastServiceAddSpy, 1, expectedToast);
expect(toastService.toasts).toBeDefined();
- expect(toastService.toasts.length).withContext(`should be 1`).toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast}`).toEqual(expectedToast);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast);
});
it('... should set durationvValue = 3000 for the toast message if delay not given ', () => {
@@ -1032,8 +946,8 @@ describe('GraphVisualizerComponent (DONE)', () => {
expectSpyCall(toastServiceAddSpy, 1, expectedToast);
expect(toastService.toasts).toBeDefined();
- expect(toastService.toasts.length).withContext(`should be 1`).toBe(1);
- expect(toastService.toasts[0]).withContext(`should equal ${expectedToast}`).toEqual(expectedToast);
+ expectToBe(toastService.toasts.length, 1);
+ expectToEqual(toastService.toasts[0], expectedToast);
});
});
@@ -1068,7 +982,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
it('... should not do anything if no node is provided', () => {
// Check initial state
expectSpyCall(performQuerySpy, 1, undefined);
- expect(component.query.queryString).toEqual(component.graphRDFInputData.queryList[0].queryString);
+ expectToBe(component.query.queryString, component.graphRDFInputData.queryList[0].queryString);
const resultsDes = getAndExpectDebugElementByDirective(compDe, ConstructResultsStubComponent, 1, 1);
const resultsCmp = resultsDes[0].injector.get(
@@ -1079,9 +993,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
resultsCmp.clickedNodeRequest.emit(undefined);
expectSpyCall(onGraphNodeClickSpy, 1, undefined);
- expect(component.query.queryString)
- .withContext(`should equal ${component.graphRDFInputData.queryList[0].queryString}`)
- .toEqual(component.graphRDFInputData.queryList[0].queryString);
+ expectToBe(component.query.queryString, component.graphRDFInputData.queryList[0].queryString);
expectSpyCall(performQuerySpy, 1, undefined);
});
@@ -1128,7 +1040,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
it('... should not do anything if no URI is provided', () => {
// Check initial state
expectSpyCall(performQuerySpy, 1, undefined);
- expect(component.query.queryString).toEqual(component.graphRDFInputData.queryList[0].queryString);
+ expectToBe(component.query.queryString, component.graphRDFInputData.queryList[0].queryString);
const resultsDes = getAndExpectDebugElementByDirective(compDe, SelectResultsStubComponent, 1, 1);
const resultsCmp = resultsDes[0].injector.get(SelectResultsStubComponent) as SelectResultsStubComponent;
@@ -1137,9 +1049,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
resultsCmp.clickedTableRequest.emit('');
expectSpyCall(onTableNodeClickSpy, 1, '');
- expect(component.query.queryString)
- .withContext(`should equal ${component.graphRDFInputData.queryList[0].queryString}`)
- .toEqual(component.graphRDFInputData.queryList[0].queryString);
+ expectToBe(component.query.queryString, component.graphRDFInputData.queryList[0].queryString);
expectSpyCall(performQuerySpy, 1, undefined);
});
@@ -1288,10 +1198,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
TriplesEditorStubComponent
) as TriplesEditorStubComponent;
- expect(editorCmp.triples).toBeDefined();
- expect(editorCmp.triples)
- .withContext(`should equal ${expectedGraphRDFData.triples}`)
- .toEqual(expectedGraphRDFData.triples);
+ expectToEqual(editorCmp.triples, expectedGraphRDFData.triples);
});
it('... should update `triples` with updateTriplesRequest event', () => {
@@ -1305,8 +1212,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
'@prefix example: .\n\n example:Test2 example:has example:Success2 .';
editorCmp.updateTriplesRequest.emit(changedTriples);
- expect(component.triples).toBeDefined();
- expect(component.triples).withContext(`should equal ${changedTriples}`).toEqual(changedTriples);
+ expectToEqual(component.triples, changedTriples);
});
it('... should re-trigger `resetTriples()` with resetTriplesRequest event', () => {
@@ -1341,15 +1247,8 @@ describe('GraphVisualizerComponent (DONE)', () => {
const editorDes = getAndExpectDebugElementByDirective(compDe, SparqlEditorStubComponent, 1, 1);
const editorCmp = editorDes[0].injector.get(SparqlEditorStubComponent) as SparqlEditorStubComponent;
- expect(editorCmp.queryList).toBeDefined();
- expect(editorCmp.queryList)
- .withContext(`should equal ${expectedGraphRDFData.queryList}`)
- .toEqual(expectedGraphRDFData.queryList);
-
- expect(editorCmp.query).toBeDefined();
- expect(editorCmp.query)
- .withContext(`should equal ${expectedGraphRDFData.queryList[0]}`)
- .toEqual(expectedGraphRDFData.queryList[0]);
+ expectToEqual(editorCmp.queryList, expectedGraphRDFData.queryList);
+ expectToEqual(editorCmp.query, expectedGraphRDFData.queryList[0]);
});
it('... should update `query.string` with updateQueryStringRequest event', () => {
@@ -1361,10 +1260,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
'PREFIX example: \n\n CONSTRUCT WHERE { ?test3 ?has ?success3 . }';
editorCmp.updateQueryStringRequest.emit(changedQueryString);
- expect(component.query.queryString).toBeDefined();
- expect(component.query.queryString)
- .withContext(`should equal ${changedQueryString}`)
- .toEqual(changedQueryString);
+ expectToBe(component.query.queryString, changedQueryString);
});
it('... should re-trigger `resetQuery()` with resetQueryRequest event', () => {
@@ -1406,8 +1302,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
expect(resultsCmp.queryResult$).toBeDefined();
resultsCmp.queryResult$.subscribe(result => {
- expect(result).toBeTruthy();
- expect(result).withContext(`should equal ${expectedResult}`).toEqual(expectedResult);
+ expectToEqual(result, expectedResult);
});
});
@@ -1417,8 +1312,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
ConstructResultsStubComponent
) as ConstructResultsStubComponent;
- expect(resultsCmp.defaultForceGraphHeight).toBeDefined();
- expect(resultsCmp.defaultForceGraphHeight).withContext('should be 500').toBe(500);
+ expectToBe(resultsCmp.defaultForceGraphHeight, 500);
});
it('... should re-trigger `onGraphNodeClick()` with clickedTableRequest event', () => {
@@ -1453,8 +1347,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
expect(resultsCmp.queryResult$).toBeDefined();
resultsCmp.queryResult$.subscribe(result => {
- expect(result).toBeTruthy();
- expect(result).withContext(`should equal ${expectedResult}`).toEqual(expectedResult);
+ expectToEqual(result, expectedResult);
});
});
@@ -1493,8 +1386,7 @@ describe('GraphVisualizerComponent (DONE)', () => {
UnsupportedTypeResultsStubComponent
) as UnsupportedTypeResultsStubComponent;
- expect(resultsCmp.queryType).toBeDefined();
- expect(resultsCmp.queryType).withContext('should be other').toBe('other');
+ expectToBe(resultsCmp.queryType, 'other');
});
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.ts
index e4b01f486..2c69c7c61 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/graph-visualizer.component.ts
@@ -188,7 +188,7 @@ export class GraphVisualizerComponent implements OnInit {
*
* @returns {void} Logs the click event.
*/
- onGraphNodeClick(node: D3SimulationNode) {
+ onGraphNodeClick(node: D3SimulationNode): void {
if (!node) {
return;
}
@@ -250,7 +250,7 @@ export class GraphVisualizerComponent implements OnInit {
* @param {string} queryString The given queryString.
* @param {string} triples THe given triples.
*
- * @returns {Promise} The result of the query as an promise of triple array.
+ * @returns {Promise} The result of the query as a promise of triple array.
*/
private async _queryLocalStore(queryType: string, queryString: string, triples: string): Promise {
// Capture start time of query
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/models/index.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/models/index.ts
index af31a4eed..2df44523d 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/models/index.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/models/index.ts
@@ -16,7 +16,6 @@ import { D3SimulationNode, D3SimulationNodeType } from './d3-simulation-node.mod
import { Namespace, NamespaceType } from './namespace.model';
import { Prefix, PrefixForm } from './prefix.model';
import { QueryResult, QueryResultBindings } from './query-result.model';
-import { QueryTypeIndex } from './query-type-index.model';
import { RDFStoreConstructResponse, RDFStoreSelectResponse } from './rdfstore-response.model';
import {
RDFStoreConstructResponseTriple,
@@ -38,9 +37,8 @@ export {
D3SimulationNodeType,
Namespace,
NamespaceType,
- PrefixForm,
Prefix,
- QueryTypeIndex,
+ PrefixForm,
QueryResult,
QueryResultBindings,
RDFStoreConstructResponse,
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/models/query-type-index.model.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/models/query-type-index.model.ts
deleted file mode 100644
index b40a6e0f5..000000000
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/models/query-type-index.model.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * The QueryTypeIndex interface.
- *
- * It represents the index of a query type.
- */
-export interface QueryTypeIndex {
- /**
- * The query type.
- */
- queryType: string;
-
- /**
- * The index of the query type.
- */
- index: number;
-}
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.spec.ts
index 7a49ab442..c5e6f60fc 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.spec.ts
@@ -1,3 +1,5 @@
+import { expectToBe } from '@testing/expect-helper';
+
import { PrefixForm } from '../models';
import { PrefixPipe } from './prefix.pipe';
@@ -15,12 +17,12 @@ describe('PrefixPipe', () => {
it('... should transform the short form of a known default RDF prefix into its long form', () => {
const pipe = new PrefixPipe();
- const shortForm = 'rdf:';
+ const shortForm = 'rdf';
const longForm = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
const transformedValue = pipe.transform(shortForm, PrefixForm.LONG);
- expect(transformedValue).toBe(longForm);
+ expectToBe(transformedValue, longForm);
});
it('... should transform the long form of a known default RDF prefix into its short form', () => {
@@ -30,7 +32,7 @@ describe('PrefixPipe', () => {
const transformedValue = pipe.transform(longForm, PrefixForm.SHORT);
- expect(transformedValue).toBe(shortForm);
+ expectToBe(transformedValue, shortForm);
});
it('... should not transform a short value that is not in the list of default RDF prefixes', () => {
@@ -39,7 +41,7 @@ describe('PrefixPipe', () => {
const transformedValue = pipe.transform(shortForm, PrefixForm.LONG);
- expect(transformedValue).toBe(shortForm);
+ expectToBe(transformedValue, shortForm);
});
it('... should not transform a long value that is not in the list of default RDF prefixes', () => {
@@ -48,7 +50,7 @@ describe('PrefixPipe', () => {
const transformedValue = pipe.transform(longForm, PrefixForm.SHORT);
- expect(transformedValue).toBe(longForm);
+ expectToBe(transformedValue, longForm);
});
it('... should throw an error if the prefixForm is not equal to PrefixForm.SHORT or PrefixForm.LONG', () => {
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.ts
index 8632fcb9e..ac420b139 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/prefix-pipe/prefix.pipe.ts
@@ -40,7 +40,7 @@ export class PrefixPipe implements PipeTransform {
case PrefixForm.LONG: {
this.defaultPrefixes.forEach((p: Prefix) => {
if (value.indexOf(p.prefixName) !== -1) {
- transformedValue = value.replace(p.prefixName + ':', p.prefixIri);
+ transformedValue = value.replace(p.prefixName, p.prefixIri);
}
});
break;
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.spec.ts
index 3631a4ebe..dcb86f368 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.spec.ts
@@ -152,9 +152,7 @@ describe('SelectResultsComponent (DONE)', () => {
it('... should have `queryResult` input', waitForAsync(() => {
expectToEqual(component.queryResult$, expectedQueryResult$);
expectAsync(lastValueFrom(component.queryResult$)).toBeResolved();
- expectAsync(lastValueFrom(component.queryResult$))
- .withContext(`should be resolved to ${expectedQueryResult}}`)
- .toBeResolvedTo(expectedQueryResult);
+ expectAsync(lastValueFrom(component.queryResult$)).toBeResolvedTo(expectedQueryResult);
}));
it('... should have `queryTime` input', () => {
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.ts
index 6c16ec154..3b5610130 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/select-results/select-results.component.ts
@@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from
import { Observable } from 'rxjs';
-import { UtilityService } from '@awg-app/core/services';
+import { UtilityService } from '@awg-core/services';
import { QueryResult } from '../models';
/**
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/services/graph-visualizer.service.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/services/graph-visualizer.service.spec.ts
index c7767d998..324ec2c9b 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/services/graph-visualizer.service.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-graph/graph-visualizer/services/graph-visualizer.service.spec.ts
@@ -1,7 +1,7 @@
import { TestBed } from '@angular/core/testing';
import Spy = jasmine.Spy;
-import { expectSpyCall } from '@testing/expect-helper';
+import { expectSpyCall, expectToBe, expectToEqual } from '@testing/expect-helper';
import { mockConsole } from '@testing/mock-helper';
import { QueryResult, RDFStoreConstructResponseTriple, Triple } from '../models';
@@ -61,7 +61,7 @@ describe('GraphVisualizerService', () => {
];
// Spies on service functions
- consoleSpy = spyOn(console, 'warn').and.callFake(mockConsole.log);
+ consoleSpy = spyOn(console, 'error').and.callFake(mockConsole.log);
});
afterEach(() => {
@@ -77,328 +77,6 @@ describe('GraphVisualizerService', () => {
expect((graphVisualizerService as any)._store).toBeUndefined();
});
- describe('#limitTriples()', () => {
- it('... should have a method `limitTriples`', () => {
- expect(graphVisualizerService.limitTriples).toBeDefined();
- });
-
- describe('should return an empty array', () => {
- it('... if triples are undefined', () => {
- const limit = 3;
-
- const result = graphVisualizerService.limitTriples(undefined, limit);
-
- expect(result).toEqual([]);
- });
-
- it('... if triples are null', () => {
- const limit = 3;
-
- const result = graphVisualizerService.limitTriples(null, limit);
-
- expect(result).toEqual([]);
- });
-
- it('... if triples are empty array', () => {
- const limit = 3;
-
- const result = graphVisualizerService.limitTriples([], limit);
-
- expect(result).toEqual([]);
- });
- });
-
- describe('should return the same Triple array', () => {
- it('... if the Triple array length is smaller than the given limit', () => {
- const inputWithTwoTriples: Triple[] = expectedTriples.slice(0, 2);
- const limit = 3;
-
- const result = graphVisualizerService.limitTriples(inputWithTwoTriples, limit);
-
- expect(result).toEqual(inputWithTwoTriples);
- });
-
- it('... if the Triple array length is equal with the given limit', () => {
- const inputWithThreeTriples: Triple[] = expectedTriples.splice(0, 3);
- const limit = 3;
-
- const result = graphVisualizerService.limitTriples(inputWithThreeTriples, limit);
-
- expect(result).toEqual(inputWithThreeTriples);
- });
- });
-
- describe('should return a limited Triple array', () => {
- it('... if the Triple array is larger than the limit', () => {
- const inputWithFourTriples: Triple[] = expectedTriples.slice(0, 4);
- const outputWithTwoTriples: Triple[] = expectedTriples.slice(0, 2);
- const outputWithThreeTriples: Triple[] = expectedTriples.splice(0, 3);
-
- const limit = 3;
-
- const result = graphVisualizerService.limitTriples(inputWithFourTriples, limit);
-
- expect(result).toEqual(outputWithThreeTriples);
-
- const limit2 = 2;
- const result2 = graphVisualizerService.limitTriples(inputWithFourTriples, limit2);
-
- expect(result2).toEqual(outputWithTwoTriples);
- });
- });
- });
-
- describe('#abbreviateTriples()', () => {
- it('... should have a method `abbreviateTriples`', () => {
- expect(graphVisualizerService.abbreviateTriples).toBeDefined();
- });
-
- describe('should abbreviate the given StoreTriples', () => {
- it('... according to the given namespaces', () => {
- const triples: RDFStoreConstructResponseTriple[] = expectedConstructResponseTriples;
- const namespaces = {
- ex: 'http://example.org/',
- exs: 'https://example.org/',
- };
-
- const result = graphVisualizerService.abbreviateTriples(triples, namespaces);
-
- expect(result[0].subject).toBeDefined();
- expect(result[0].predicate).toBeDefined();
- expect(result[0].object).toBeDefined();
- expect(result[0].subject).withContext(`should be 'ex:subject1'`).toBe('ex:subject1');
- expect(result[0].predicate).withContext(`should be 'ex:predicate1'`).toBe('ex:predicate1');
- expect(result[0].object).withContext(`should be 'ex:object1'`).toBe('ex:object1');
-
- expect(result[1].subject).toBeDefined();
- expect(result[1].predicate).toBeDefined();
- expect(result[1].object).toBeDefined();
- expect(result[1].subject).withContext(`should be 'exs:subject2'`).toBe('exs:subject2');
- expect(result[1].predicate).withContext(`should be 'exs:predicate2'`).toBe('exs:predicate2');
- expect(result[1].object).withContext(`should be 'exs:object2'`).toBe('exs:object2');
- });
-
- it('... if mimetype `text/turtle` is given', () => {
- const triples: RDFStoreConstructResponseTriple[] = expectedConstructResponseTriples;
- const namespaces = {
- ex: 'http://example.org/',
- exs: 'https://example.org/',
- };
- const mimetypeTurtle = 'text/turtle';
-
- const result = graphVisualizerService.abbreviateTriples(triples, namespaces, mimetypeTurtle);
-
- expect(result[0].subject).toBeDefined();
- expect(result[0].predicate).toBeDefined();
- expect(result[0].object).toBeDefined();
- expect(result[0].subject).withContext(`should be 'ex:subject1'`).toBe('ex:subject1');
- expect(result[0].predicate).withContext(`should be 'ex:predicate1'`).toBe('ex:predicate1');
- expect(result[0].object).withContext(`should be 'ex:object1'`).toBe('ex:object1');
-
- expect(result[1].subject).toBeDefined();
- expect(result[1].predicate).toBeDefined();
- expect(result[1].object).toBeDefined();
- expect(result[1].subject).withContext(`should be 'exs:subject2'`).toBe('exs:subject2');
- expect(result[1].predicate).withContext(`should be 'exs:predicate2'`).toBe('exs:predicate2');
- expect(result[1].object).withContext(`should be 'exs:object2'`).toBe('exs:object2');
- });
-
- it('... if no mimetype is given (`text/turtle` applied by default)', () => {
- const triples: RDFStoreConstructResponseTriple[] = expectedConstructResponseTriples;
- const namespaces = {
- ex: 'http://example.org/',
- exs: 'https://example.org/',
- };
- const mimetypeEmpty = '';
-
- const result = graphVisualizerService.abbreviateTriples(triples, namespaces, mimetypeEmpty);
-
- expect(result[0].subject).toBeDefined();
- expect(result[0].predicate).toBeDefined();
- expect(result[0].object).toBeDefined();
- expect(result[0].subject).withContext(`should be 'ex:subject1'`).toBe('ex:subject1');
- expect(result[0].predicate).withContext(`should be 'ex:predicate1'`).toBe('ex:predicate1');
- expect(result[0].object).withContext(`should be 'ex:object1'`).toBe('ex:object1');
-
- expect(result[1].subject).toBeDefined();
- expect(result[1].predicate).toBeDefined();
- expect(result[1].object).toBeDefined();
- expect(result[1].subject).withContext(`should be 'exs:subject2'`).toBe('exs:subject2');
- expect(result[1].predicate).withContext(`should be 'exs:predicate2'`).toBe('exs:predicate2');
- expect(result[1].object).withContext(`should be 'exs:object2'`).toBe('exs:object2');
- });
- });
-
- describe('should not abbreviate the given StoreTriples', () => {
- it('... if the IRI uses an unknown namespace', () => {
- const triples: RDFStoreConstructResponseTriple[] = expectedConstructResponseTriples;
- const namespaces = {};
-
- const result = graphVisualizerService.abbreviateTriples(triples, namespaces);
-
- expect(result[0].subject).toBeDefined();
- expect(result[0].predicate).toBeDefined();
- expect(result[0].object).toBeDefined();
- expect(result[0].subject)
- .withContext(`should be 'http://example.org/subject1'`)
- .toBe('http://example.org/subject1');
- expect(result[0].predicate)
- .withContext(`should be 'http://example.org/predicate1'`)
- .toBe('http://example.org/predicate1');
- expect(result[0].object)
- .withContext(`should be 'http://example.org/object1'`)
- .toBe('http://example.org/object1');
-
- expect(result[1].subject).toBeDefined();
- expect(result[1].predicate).toBeDefined();
- expect(result[1].object).toBeDefined();
- expect(result[1].subject)
- .withContext(`should be 'https://example.org/subject2'`)
- .toBe('https://example.org/subject2');
- expect(result[1].predicate)
- .withContext(`should be 'https://example.org/predicate2'`)
- .toBe('https://example.org/predicate2');
- expect(result[1].object)
- .withContext(`should be 'https://example.org/object2'`)
- .toBe('https://example.org/object2');
- });
-
- it('... if a given mimetype is not `text/turtle`', () => {
- const triples: RDFStoreConstructResponseTriple[] = expectedConstructResponseTriples;
- const namespaces = {
- ex: 'http://example.org/',
- exs: 'https://example.org/',
- };
- const mimetypePlain = 'text/plain';
-
- const result = graphVisualizerService.abbreviateTriples(triples, namespaces, mimetypePlain);
-
- expect(result[0].subject).toBeDefined();
- expect(result[0].predicate).toBeDefined();
- expect(result[0].object).toBeDefined();
- expect(result[0].subject)
- .withContext(`should be 'http://example.org/subject1'`)
- .toBe('http://example.org/subject1');
- expect(result[0].predicate)
- .withContext(`should be 'http://example.org/predicate1'`)
- .toBe('http://example.org/predicate1');
- expect(result[0].object)
- .withContext(`should be 'http://example.org/object1'`)
- .toBe('http://example.org/object1');
-
- expect(result[1].subject).toBeDefined();
- expect(result[1].predicate).toBeDefined();
- expect(result[1].object).toBeDefined();
- expect(result[1].subject)
- .withContext(`should be 'https://example.org/subject2'`)
- .toBe('https://example.org/subject2');
- expect(result[1].predicate)
- .withContext(`should be 'https://example.org/predicate2'`)
- .toBe('https://example.org/predicate2');
- expect(result[1].object)
- .withContext(`should be 'https://example.org/object2'`)
- .toBe('https://example.org/object2');
- });
- });
- });
-
- describe('#getQuerytype()', () => {
- it('... should have a method `getQuerytype`', () => {
- expect(graphVisualizerService.getQuerytype).toBeDefined();
- });
-
- describe('should return correct querytpe', () => {
- it('... if the query is a SELECT query (= `select`)', () => {
- const query = 'SELECT * WHERE { ?s ?p ?o }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `select`').toBe('select');
- });
-
- it('... if the query is a CONSTRUCT query (= `construct`)', () => {
- const query = 'CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `construct`').toBe('construct');
- });
-
- it('... if the query is an ASK query (= `ask`)', () => {
- const query = 'ASK WHERE { ?s ?p ?o }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `ask`').toBe('ask');
- });
-
- it('... if the query is a DESCRIBE query (= `describe`)', () => {
- const query = 'DESCRIBE ?s WHERE { ?s ?p ?o }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `describe`').toBe('describe');
- });
-
- it('... if the query is a COUNT query (= `count`)', () => {
- const query = 'COUNT ?s WHERE { ?s ?p ?o }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `count`').toBe('count');
- });
-
- it('... if the query is a DELETE query (= `update`)', () => {
- const query = 'DELETE {?s ?p ?o } WHERE { ?s ?p ?o }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `update`').toBe('update');
- });
-
- it('... if the query is an INSERT query (= `update`)', () => {
- const query = 'INSERT { ?s ?p ?o } WHERE { ?s ?p ?o} ';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `update`').toBe('update');
- });
-
- it('... if the query starts with prefixes', () => {
- const query = 'PREFIX ex: SELECT * WHERE { ?s ?p ?o }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `select`').toBe('select');
- });
- });
-
- it('... should return the first query type if the query uses multiple query types', () => {
- const query = 'CONSTRUCT { ?s ?p ?y } WHERE { SELECT ?s ?p ( bnode() AS ?y ) WHERE { ?s ?p ?o } }';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBeDefined();
- expect(result).withContext('should be `construct`').toBe('construct');
- });
-
- it('... should return `null` if the query is not a SELECT, CONSTRUCT, ASK, COUNT, DESCRIBE, INSERT or DELETE query', () => {
- const query = 'LOAD ';
-
- const result = graphVisualizerService.getQuerytype(query);
-
- expect(result).toBe(null);
- });
- });
-
describe('#checkNamespacesInQuery()', () => {
it('... should have a method `checkNamespacesInQuery`', () => {
expect(graphVisualizerService.checkNamespacesInQuery).toBeDefined();
@@ -410,7 +88,7 @@ describe('GraphVisualizerService', () => {
'@prefix ex: ';
const result = graphVisualizerService.checkNamespacesInQuery(undefined, tripleStr);
- expect(result).toBe(undefined);
+ expect(result).toBeUndefined();
});
it('... if no tripleString is given', () => {
@@ -418,13 +96,13 @@ describe('GraphVisualizerService', () => {
const result = graphVisualizerService.checkNamespacesInQuery(queryStr, undefined);
- expect(result).toBe(undefined);
+ expect(result).toBeUndefined();
});
it('... if no queryString and tripleString is given', () => {
const result = graphVisualizerService.checkNamespacesInQuery(undefined, undefined);
- expect(result).toBe(undefined);
+ expect(result).toBeUndefined();
});
});
@@ -436,32 +114,20 @@ describe('GraphVisualizerService', () => {
const result = graphVisualizerService.checkNamespacesInQuery(queryStr, tripleStr);
- expect(result).toBeDefined();
- expect(result).withContext(`should be ${expectedResult}`).toBe(expectedResult);
+ expectToBe(result, expectedResult);
});
describe('should check qNames from the query if a qName is not referenced in the list of namespaces and ...', () => {
describe('if the qName is not in the list of default namespaces', () => {
- it('... warn in the console ', () => {
+ it('... error in the console ', () => {
const tripleStr =
'@prefix ex: . ';
const queryStr = 'SELECT * WHERE { ?s xyz:composer ?o }';
- const expectedFirstWarning = `Prefix 'xyz:' not declared in SPARQL and/or Turtle header. Searching in default namespaces...`;
- const expectedSecondWarning = `'xyz:' is unknown. Please provide a declaration.`;
+ const expectedError = `Prefix 'xyz' is unknown. Please provide a declaration.`;
graphVisualizerService.checkNamespacesInQuery(queryStr, tripleStr);
- expectSpyCall(consoleSpy, 2);
-
- expect(consoleSpy.calls.argsFor(0)).toBeDefined();
- expect(consoleSpy.calls.argsFor(0))
- .withContext(`should equal ${expectedFirstWarning}`)
- .toEqual([expectedFirstWarning]);
-
- expect(consoleSpy.calls.argsFor(1)).toBeDefined();
- expect(consoleSpy.calls.argsFor(1))
- .withContext(`should equal ${expectedSecondWarning}`)
- .toEqual([expectedSecondWarning]);
+ expectSpyCall(consoleSpy, 1, [expectedError]);
});
});
@@ -474,30 +140,7 @@ describe('GraphVisualizerService', () => {
const result = graphVisualizerService.checkNamespacesInQuery(queryStr, tripleStr);
- expect(result).toBeDefined();
- expect(result.trim()).withContext(`should be ${expectedResult}`).toBe(expectedResult);
- });
-
- it('... warn in the console ', () => {
- const tripleStr =
- '@prefix ex: .\n .';
- const queryStr = 'PREFIX ex: \nSELECT * WHERE { ?s foaf:age ?o }';
- const expectedFirstWarning = `Prefix 'foaf:' not declared in SPARQL and/or Turtle header. Searching in default namespaces...`;
- const expectedSecondWarning = `Added 'PREFIX foaf: \n' to SPARQL prefixes from list of default namespaces.`;
-
- graphVisualizerService.checkNamespacesInQuery(queryStr, tripleStr);
-
- expectSpyCall(consoleSpy, 2);
-
- expect(consoleSpy.calls.argsFor(0)).toBeDefined();
- expect(consoleSpy.calls.argsFor(0))
- .withContext(`should equal ${expectedFirstWarning}`)
- .toEqual([expectedFirstWarning]);
-
- expect(consoleSpy.calls.argsFor(1)).toBeDefined();
- expect(consoleSpy.calls.argsFor(1))
- .withContext(`should equal ${expectedSecondWarning}`)
- .toEqual([expectedSecondWarning]);
+ expectToBe(result, expectedResult);
});
});
});
@@ -507,9 +150,9 @@ describe('GraphVisualizerService', () => {
'@prefix ex: . ';
const expectedError = 'The type must be TURTLE or SPARQL, but was: undefined.';
- expect(() => (graphVisualizerService as any)._extractNamespacesFromString(undefined, tripleStr))
- .withContext('should throw an error')
- .toThrowError(expectedError);
+ expect(() =>
+ (graphVisualizerService as any)._extractNamespacesFromString(undefined, tripleStr)
+ ).toThrowError(expectedError);
});
});
@@ -527,6 +170,7 @@ describe('GraphVisualizerService', () => {
await graphVisualizerService.doQuery(queryType, queryStr, tripleStr);
expect((graphVisualizerService as any)._store).toBeDefined();
+ expectToEqual((graphVisualizerService as any)._store.constructor.name, 'Store');
});
describe('should perform a given query with a given turtle string against the rdfstore', () => {
@@ -545,8 +189,7 @@ describe('GraphVisualizerService', () => {
const result = await graphVisualizerService.doQuery(queryType, queryStr, tripleStr);
- expect(result).toBeDefined();
- expect(result).withContext(`should equal ${expectedConstructResult}`).toEqual(expectedConstructResult);
+ expectToEqual(result, expectedConstructResult);
});
it('... and return QueryResult with SELECT query', async () => {
@@ -583,8 +226,7 @@ describe('GraphVisualizerService', () => {
const result = await graphVisualizerService.doQuery(queryType, queryStr, tripleStr);
- expect(result).toBeDefined();
- expect(result).withContext(`should equal ${expectedSelectResult}`).toEqual(expectedSelectResult);
+ expectToEqual(result, expectedSelectResult);
});
it('... and transform integer literals to number labels in a SELECT response', async () => {
@@ -643,8 +285,7 @@ describe('GraphVisualizerService', () => {
const result = await graphVisualizerService.doQuery(queryType, queryStr, tripleStr);
- expect(result).toBeDefined();
- expect(result).withContext(`should equal ${expectedSelectResult}`).toEqual(expectedSelectResult);
+ expectToEqual(result, expectedSelectResult);
});
describe('... and return `undefined`', () => {
@@ -684,27 +325,1387 @@ describe('GraphVisualizerService', () => {
const result = await graphVisualizerService.doQuery(queryType, queryStr, tripleStr);
- expect(result).toBeDefined();
- expect(result).withContext(`should equal ${expectedResponse}`).toEqual(expectedResponse);
+ expectToEqual(result, expectedResponse);
});
});
});
- describe('#parseTripleString()', () => {
- it('... should have a method `parseTripleString`', () => {
- expect(graphVisualizerService.parseTripleString).toBeDefined();
+ describe('#getQuerytype()', () => {
+ it('... should have a method `getQuerytype`', () => {
+ expect(graphVisualizerService.getQuerytype).toBeDefined();
});
- it('... should return a Promise of triples and namespaces', async () => {
- const triples =
- '@prefix ex: . .';
+ describe('should return correct querytpe', () => {
+ it('... if the query is a SELECT query (= `select`)', () => {
+ const query = 'SELECT * WHERE { ?s ?p ?o }';
- const result = graphVisualizerService.parseTripleString(triples);
+ const result = graphVisualizerService.getQuerytype(query);
- expect(result).toBeDefined();
- await expectAsync(result).toBeResolved();
+ expectToBe(result, 'select');
+ });
+
+ it('... if the query is a CONSTRUCT query (= `construct`)', () => {
+ const query = 'CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'construct');
+ });
+
+ it('... if the query is an ASK query (= `ask`)', () => {
+ const query = 'ASK WHERE { ?s ?p ?o }';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'ask');
+ });
+
+ it('... if the query is a DESCRIBE query (= `describe`)', () => {
+ const query = 'DESCRIBE ?s WHERE { ?s ?p ?o }';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'describe');
+ });
+
+ it('... if the query is a COUNT query (= `count`)', () => {
+ const query = 'COUNT ?s WHERE { ?s ?p ?o }';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'count');
+ });
+
+ it('... if the query is a DELETE query (= `update`)', () => {
+ const query = 'DELETE {?s ?p ?o } WHERE { ?s ?p ?o }';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'update');
+ });
+
+ it('... if the query is an INSERT query (= `update`)', () => {
+ const query = 'INSERT { ?s ?p ?o } WHERE { ?s ?p ?o} ';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'update');
+ });
+
+ it('... if the query starts with prefixes', () => {
+ const query = 'PREFIX ex: SELECT * WHERE { ?s ?p ?o }';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'select');
+ });
+ });
+
+ it('... should return the first query type if the query uses multiple query types', () => {
+ const query = 'CONSTRUCT { ?s ?p ?y } WHERE { SELECT ?s ?p ( bnode() AS ?y ) WHERE { ?s ?p ?o } }';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, 'construct');
+ });
+
+ it('... should return `null` if the query is not a SELECT, CONSTRUCT, ASK, COUNT, DESCRIBE, INSERT or DELETE query', () => {
+ const query = 'LOAD ';
+
+ const result = graphVisualizerService.getQuerytype(query);
+
+ expectToBe(result, null);
+ });
+ });
+
+ describe('#limitTriples()', () => {
+ it('... should have a method `limitTriples`', () => {
+ expect(graphVisualizerService.limitTriples).toBeDefined();
+ });
+
+ describe('should return an empty array', () => {
+ it('... if triples are undefined', () => {
+ const limit = 3;
+
+ const result = graphVisualizerService.limitTriples(undefined, limit);
+
+ expectToEqual(result, []);
+ });
+
+ it('... if triples are null', () => {
+ const limit = 3;
+
+ const result = graphVisualizerService.limitTriples(null, limit);
+
+ expectToEqual(result, []);
+ });
+
+ it('... if triples are empty array', () => {
+ const limit = 3;
+
+ const result = graphVisualizerService.limitTriples([], limit);
+
+ expectToEqual(result, []);
+ });
+ });
+
+ describe('should return the original Triple array', () => {
+ it('... if the Triple array length is smaller than the given limit', () => {
+ const inputWithTwoTriples: Triple[] = expectedTriples.slice(0, 2);
+ const limit = 3;
+
+ const result = graphVisualizerService.limitTriples(inputWithTwoTriples, limit);
+
+ expectToEqual(result, inputWithTwoTriples);
+ });
+
+ it('... if the Triple array length is equal with the given limit', () => {
+ const inputWithThreeTriples: Triple[] = expectedTriples.splice(0, 3);
+ const limit = 3;
+
+ const result = graphVisualizerService.limitTriples(inputWithThreeTriples, limit);
+
+ expectToEqual(result, inputWithThreeTriples);
+ });
+ });
+
+ describe('should return a limited Triple array', () => {
+ it('... if the Triple array is larger than the limit', () => {
+ const inputWithFourTriples: Triple[] = expectedTriples.slice(0, 4);
+ const outputWithTwoTriples: Triple[] = expectedTriples.slice(0, 2);
+ const outputWithThreeTriples: Triple[] = expectedTriples.splice(0, 3);
+
+ const limit = 3;
+
+ const result = graphVisualizerService.limitTriples(inputWithFourTriples, limit);
+
+ expectToEqual(result, outputWithThreeTriples);
+
+ const limit2 = 2;
+ const result2 = graphVisualizerService.limitTriples(inputWithFourTriples, limit2);
+
+ expectToEqual(result2, outputWithTwoTriples);
+ });
+ });
+ });
+
+ describe('#parseTripleString()', () => {
+ it('... should have a method `parseTripleString`', () => {
+ expect(graphVisualizerService.parseTripleString).toBeDefined();
+ });
+
+ it('... should return a Promise of triples and namespaces for a given triple string', async () => {
+ const triples =
+ '@prefix ex: . @prefix ex2: . .';
+
+ await expectAsync(graphVisualizerService.parseTripleString(triples)).toBeResolved();
+
+ const result = await graphVisualizerService.parseTripleString(triples);
+
+ expect(result).toBeDefined();
+ expectToEqual(result.namespaces, { ex: 'http://example.org/', ex2: 'http://example2.org/' });
+ expectToBe(Array.isArray(result.quads), true);
+ expectToBe(result.quads.length, 1);
+ expectToBe(result.quads[0].subject.id, 'http://example.org/subject');
+ expectToBe(result.quads[0].predicate.id, 'http://example.org/predicate');
+ expectToBe(result.quads[0].object.id, 'http://example.org/object');
+ });
+
+ it('... should return a Promise of empty triples and namespaces for an empty triple string', async () => {
+ const triples = '';
+
+ await expectAsync(graphVisualizerService.parseTripleString(triples)).toBeResolved();
+
+ const result = await graphVisualizerService.parseTripleString(triples);
+
+ expect(result).toBeDefined();
+ expectToEqual(result.namespaces, {});
+ expectToBe(Array.isArray(result.quads), true);
+ expectToBe(result.quads.length, 0);
+ });
+
+ describe('... should throw an error', () => {
+ it('... for missing dots', async () => {
+ const triplesWithSyntaxError =
+ '@prefix ex: @prefix ex2: . .';
+
+ await expectAsync(
+ graphVisualizerService.parseTripleString(triplesWithSyntaxError)
+ ).toBeRejectedWithError('Expected declaration to end with a dot on line 1.');
+ });
+
+ it('... for missing @', async () => {
+ const triplesWithSyntaxError =
+ 'prefix ex: . @prefix ex2: . .';
+
+ await expectAsync(
+ graphVisualizerService.parseTripleString(triplesWithSyntaxError)
+ ).toBeRejectedWithError('Expected entity but got . on line 1.');
+ });
+
+ it('... for missing prefix marker', async () => {
+ const triplesWithSyntaxError =
+ '@prefix ex: . ex2: . .';
+
+ await expectAsync(
+ graphVisualizerService.parseTripleString(triplesWithSyntaxError)
+ ).toBeRejectedWithError('Undefined prefix "ex2:" on line 1.');
+ });
+ });
+ });
+
+ describe('#_abbreviate()', () => {
+ it('... should have a method `_abbreviate`', () => {
+ expect((graphVisualizerService as any)._abbreviate).toBeDefined();
+ });
+
+ describe('... should return an abbreviated IRI if', () => {
+ it('... the given IRI matches a given namespace', () => {
+ const iri = 'http://example.org/subject';
+ const namespaces = { ex: 'http://example.org/' };
+ const expectedAbbreviation = 'ex:subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the given IRI matches one of the provided namespaces', () => {
+ const iri = 'http://example2.org/subject';
+ const namespaces = {
+ ex: 'http://example.org/',
+ ex2: 'http://example2.org/',
+ ex3: 'http://example3.org/',
+ };
+ const expectedAbbreviation = 'ex2:subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the given IRI matches multiple namespaces (using the first matching namespace)', () => {
+ const iri = 'http://example.com/subject';
+ const namespaces = {
+ other: 'http://other.org/subject',
+ ex1: 'http://example.com/',
+ ex2: 'http://example.com/',
+ ex3: 'http://example.com/',
+ };
+ const expectedAbbreviation = 'ex1:subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expect(result).toBe(expectedAbbreviation);
+ });
+ });
+
+ describe('... should return a partially (incorrect) abbreviated IRI if', () => {
+ it('... the namespace does not have a trailing slash', () => {
+ const iri = 'http://example.org/subject';
+ const namespaces = { ex: 'http://example.org' };
+ const expectedAbbreviation = 'ex:/subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the namespace does not have a trailing hash', () => {
+ const iri = 'http://example.org#subject';
+ const namespaces = { ex: 'http://example.org' };
+ const expectedAbbreviation = 'ex:#subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the namespace matches the IRI exactly', () => {
+ const iri = 'http://example.org/';
+ const namespaces = { ex: 'http://example.org/' };
+ const expectedAbbreviation = 'ex:';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+ });
+
+ describe('... should return the original IRI if', () => {
+ it('... the given IRI does not start with http', () => {
+ const notFullIri = 'ex:subject';
+ const namespaces = { ex: 'http://example.org/' };
+ const expectedAbbreviation = 'ex:subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(notFullIri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... no namespaces are provided', () => {
+ const iri = 'http://example.org/subject';
+ const namespaces = {};
+ const expectedAbbreviation = 'http://example.org/subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the given namespaces are undefined or null', () => {
+ const iri = 'http://example.org/subject';
+ const namespaces = undefined;
+ const expectedAbbreviation = 'http://example.org/subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+
+ const namespaces2 = null;
+
+ const result2 = (graphVisualizerService as any)._abbreviate(iri, namespaces2);
+
+ expectToBe(result2, expectedAbbreviation);
+ });
+
+ it('... the given IRI does not match a given namespace', () => {
+ const notMatchingIri = 'http://other.org/subject';
+ const namespaces = { ex: 'http://example.org/' };
+ const expectedAbbreviation = 'http://other.org/subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(notMatchingIri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the given IRI does not match any of the provided namespaces', () => {
+ const notMatchingIri = 'http://other.org/subject';
+ const namespaces = {
+ ex: 'http://example.org/',
+ ex2: 'http://example2.org/',
+ ex3: 'http://example3.org/',
+ };
+ const expectedAbbreviation = 'http://other.org/subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(notMatchingIri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the given IRI does not match a given namespace respecting case sensitivity', () => {
+ const iri = 'http://example.org/subject';
+ const namespaces = { ex: 'http://EXAMPLE.org/' };
+ const expectedAbbreviation = 'http://example.org/subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+
+ it('... the given IRI only partially matches a given namespace', () => {
+ const iri = 'http://example.org#subject';
+ const namespaces = { ex: 'http://example.org/' };
+ const expectedAbbreviation = 'http://example.org#subject';
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, expectedAbbreviation);
+ });
+ });
+
+ it('... should return `undefined` if the given IRI is undefined', () => {
+ const iri = undefined;
+ const namespaces = { ex: 'http://example.org/' };
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expect(result).toBeUndefined();
+ });
+
+ it('... should return `null` if the given IRI is null', () => {
+ const iri = null;
+ const namespaces = { ex: 'http://example.org/' };
+
+ const result = (graphVisualizerService as any)._abbreviate(iri, namespaces);
+
+ expectToBe(result, null);
+ });
+ });
+
+ describe('#_createStore()', () => {
+ it('... should have a method `_createStore`', () => {
+ expect((graphVisualizerService as any)._createStore).toBeDefined();
+ });
+
+ it('... should return a Promise of an rdfstore instance', async () => {
+ await expectAsync((graphVisualizerService as any)._createStore(global.rdfstore)).toBeResolved();
+ });
+
+ it('... should return a Promise of an rdfstore instance with load and execute methods', async () => {
+ const result = await (graphVisualizerService as any)._createStore(global.rdfstore);
+
+ expect(result).toBeDefined();
+ expectToBe(result.constructor.name, 'Store');
+ expect(result.load).toBeDefined();
+ expect(result.execute).toBeDefined();
+ });
+
+ it('... should reject if store.create encounters an error', async () => {
+ const expectedError = new Error('Test error');
+ const mockStore = {
+ create: callback => {
+ callback(expectedError, null);
+ },
+ };
+
+ const storeSpy = spyOn(mockStore, 'create').and.callThrough();
+
+ await expectAsync((graphVisualizerService as any)._createStore(mockStore)).toBeRejectedWith(expectedError);
+
+ expectSpyCall(storeSpy, 1, [jasmine.any(Function)]);
+ });
+ });
+
+ describe('#_executeQuery()', () => {
+ let store;
+
+ beforeEach(async () => {
+ store = await (graphVisualizerService as any)._createStore(global.rdfstore);
+
+ let tripleStr =
+ '@prefix ex: . @prefix ex1: . @prefix ex2: .';
+
+ for (let i = 1; i <= 2; i++) {
+ tripleStr += ` . `;
+ }
+
+ await (graphVisualizerService as any)._loadTriplesInStore(store, tripleStr);
+ });
+
+ it('... should have a method `_executeQuery`', () => {
+ expect((graphVisualizerService as any)._executeQuery).toBeDefined();
+ });
+
+ it('... should resolve a construct response for a CONSTRUCT query', async () => {
+ const query = 'CONSTRUCT WHERE { ?s ?p ?o . }';
+ const expectedQueryResult = [
+ ' .',
+ ' .',
+ ];
+
+ const result = await (graphVisualizerService as any)._executeQuery(store, query);
+
+ expectToBe(result.triples.length, 2);
+ result.triples.forEach((triple, index: number) => {
+ expectToBe(triple.toString().trim(), expectedQueryResult[index]);
+ });
+ });
+
+ it('... should resolve a select response for a SELECT query', async () => {
+ const query = 'SELECT * WHERE { ?s ?p ?o . }';
+ const expectedQueryResult = [
+ {
+ s: { token: 'uri', value: 'http://example.org/subject1' },
+ p: { token: 'uri', value: 'http://example.org/predicate1' },
+ o: { token: 'uri', value: 'http://example.org/object1' },
+ },
+ {
+ s: { token: 'uri', value: 'http://example.org/subject2' },
+ p: { token: 'uri', value: 'http://example.org/predicate2' },
+ o: { token: 'uri', value: 'http://example.org/object2' },
+ },
+ ];
+
+ const result = await (graphVisualizerService as any)._executeQuery(store, query);
+
+ expectToBe(result.length, 2);
+ result.forEach((triple, index: number) => {
+ expectToEqual(triple, expectedQueryResult[index]);
+ });
+ });
+
+ it('... should reject if query is empty', async () => {
+ const emptyQuery = '';
+
+ await expectAsync((graphVisualizerService as any)._executeQuery(store, emptyQuery)).toBeRejected();
+ });
+
+ it('... should reject and throw/log an error if store.execute encounters an error', async () => {
+ const expectedError = new Error('Test error');
+ const mockStore = {
+ execute: (query, callback) => {
+ callback(expectedError, null);
+ },
+ };
+
+ const storeSpy = spyOn(mockStore, 'execute').and.callThrough();
+
+ const testQuery = 'SELECT * WHERE { ?s ?p ?o }';
+
+ await expectAsync((graphVisualizerService as any)._executeQuery(mockStore, testQuery)).toBeRejectedWith(
+ expectedError
+ );
+
+ expectSpyCall(storeSpy, 1, [testQuery, jasmine.any(Function)]);
+ expectSpyCall(consoleSpy, 1, ['_executeQuery# got ERROR', expectedError]);
+ });
+ });
+
+ describe('#_extractNamespacesFromString()', () => {
+ it('... should have a method `_extractNamespacesFromString`', () => {
+ expect((graphVisualizerService as any)._extractNamespacesFromString).toBeDefined();
+ });
+
+ it('... should return an object with namespaces from a given turtle string', () => {
+ const turtleStr =
+ '@prefix ex: . @prefix ex2: . .';
+ const expectedNamespaces = { ex: 'http://example.org/', ex2: 'http://example2.org' };
+
+ const result = (graphVisualizerService as any)._extractNamespacesFromString('TURTLE', turtleStr);
+
+ expectToEqual(result, expectedNamespaces);
+ });
+
+ it('... should return an object with namespaces from a given SPARQL string', () => {
+ const sparqlStr =
+ 'PREFIX ex: . PREFIX ex2: . SELECT * WHERE { ?s ?p ?o }';
+ const expectedNamespaces = { ex: 'http://example.org/', ex2: 'http://example2.org' };
+
+ const result = (graphVisualizerService as any)._extractNamespacesFromString('SPARQL', sparqlStr);
+
+ expectToEqual(result, expectedNamespaces);
+ });
+
+ describe('... should return an empty object if', () => {
+ it('... the given string is empty', () => {
+ const emptyStr = '';
+ const expectedNamespaces = {};
+
+ const result = (graphVisualizerService as any)._extractNamespacesFromString('TURTLE', emptyStr);
+
+ expectToEqual(result, expectedNamespaces);
+
+ const result2 = (graphVisualizerService as any)._extractNamespacesFromString('SPARQL', emptyStr);
+
+ expectToEqual(result2, expectedNamespaces);
+ });
+
+ it('... the given string has no prefixes in TURTLE', () => {
+ const noPrefixTurtleStr =
+ ' .';
+ const expectedNamespaces = {};
+
+ const result = (graphVisualizerService as any)._extractNamespacesFromString(
+ 'TURTLE',
+ noPrefixTurtleStr
+ );
+
+ expectToEqual(result, expectedNamespaces);
+ });
+
+ it('... the given string has no prefixes in SPARQL', () => {
+ const noPrefixSparqlStr = 'SELECT * WHERE { ?s ?p ?o }';
+ const expectedNamespaces = {};
+
+ const result = (graphVisualizerService as any)._extractNamespacesFromString(
+ 'SPARQL',
+ noPrefixSparqlStr
+ );
+
+ expectToEqual(result, expectedNamespaces);
+ });
+ });
+
+ it('... should throw an error if called with another type than TURTLE or SPARQL', () => {
+ const tripleStr =
+ '@prefix ex: . ';
+ const expectedError = 'The type must be TURTLE or SPARQL, but was: OTHER.';
+
+ expect(() => (graphVisualizerService as any)._extractNamespacesFromString('OTHER', tripleStr)).toThrowError(
+ expectedError
+ );
+ });
+ });
+
+ describe('#_extractQNamePrefixesFromSPARQLWhereClause()', () => {
+ it('... should have a method `_extractQNamePrefixesFromSPARQLWhereClause`', () => {
+ expect((graphVisualizerService as any)._extractQNamePrefixesFromSPARQLWhereClause).toBeDefined();
+ });
+
+ it('... should return an empty array if no prefixes are in the where clause', () => {
+ const query = 'SELECT * WHERE { ?s ?p ?o . }';
+ const expectedPrefixes = [];
+
+ const result = (graphVisualizerService as any)._extractQNamePrefixesFromSPARQLWhereClause(query);
+
+ expectToEqual(result, expectedPrefixes);
+ });
+
+ it('... should return an array of prefixes from the where clause', () => {
+ const query = 'SELECT * WHERE { ex:s ex1:p ex2:o .}';
+ const expectedPrefixes = ['ex', 'ex1', 'ex2'];
+
+ const result = (graphVisualizerService as any)._extractQNamePrefixesFromSPARQLWhereClause(query);
+
+ expectToEqual(result, expectedPrefixes);
+ });
+
+ it('... should return an array of unique prefixes from the where clause', () => {
+ const query = 'SELECT * WHERE { ex:s ex1:p ex2:o . ex:s1 ex1:p1 ex2:o1 .}';
+ const expectedPrefixes = ['ex', 'ex1', 'ex2'];
+
+ const result = (graphVisualizerService as any)._extractQNamePrefixesFromSPARQLWhereClause(query);
+
+ expectToEqual(result, expectedPrefixes);
+ });
+
+ it('... should return an array of unique prefixes from the where clause respecting case sensitivity', () => {
+ const query =
+ 'SELECT * WHERE { ex:s ex1:p ex2:o . Ex:s1 Ex1:p1 Ex2:o1 . EX:s2 EX1:p2 EX2:o2 . eX:s3 eX1:p3 eX2:o3 .}';
+ const expectedPrefixes = ['ex', 'ex1', 'ex2', 'Ex', 'Ex1', 'Ex2', 'EX', 'EX1', 'EX2', 'eX', 'eX1', 'eX2'];
+
+ const result = (graphVisualizerService as any)._extractQNamePrefixesFromSPARQLWhereClause(query);
+
+ expectToEqual(result, expectedPrefixes);
+ });
+
+ it('... should find prefixes when no where keyword is given', () => {
+ const query = 'SELECT * { ex:s ex1:p ex2:o . ex:s1 ex1:p1 ex2:o1 .}';
+ const expectedPrefixes = ['ex', 'ex1', 'ex2'];
+
+ const result = (graphVisualizerService as any)._extractQNamePrefixesFromSPARQLWhereClause(query);
+
+ expectToEqual(result, expectedPrefixes);
+ });
+
+ it('... should find prefixes starting with underscore, small letter or capital letter', () => {
+ const query = 'SELECT * WHERE { _:s Ex1:p EX2:o . ex:s1 ex1:p1 ex2:o1 .}';
+ const expectedPrefixes = ['_', 'Ex1', 'EX2', 'ex', 'ex1', 'ex2'];
+
+ const result = (graphVisualizerService as any)._extractQNamePrefixesFromSPARQLWhereClause(query);
+
+ expectToEqual(result, expectedPrefixes);
+ });
+ });
+
+ describe('#_loadTriplesInStore()', () => {
+ let store;
+
+ beforeEach(async () => {
+ store = await (graphVisualizerService as any)._createStore(global.rdfstore);
+ });
+
+ it('... should have a method `_loadTriplesInStore`', () => {
+ expect((graphVisualizerService as any)._loadTriplesInStore).toBeDefined();
+ });
+
+ it('... should load a single triple into the rdfstore', async () => {
+ const tripleStr =
+ '@prefix ex: . .';
+ const expectedSize = 1;
+
+ const size = await (graphVisualizerService as any)._loadTriplesInStore(store, tripleStr);
+
+ expectToBe(size, expectedSize);
+ });
+
+ it('... should load multiple triples into the rdfstore', async () => {
+ const tripleStr =
+ '@prefix ex: . . ' +
+ ' ;' +
+ ' .';
+ const expectedSize = 3;
+
+ const size = await (graphVisualizerService as any)._loadTriplesInStore(store, tripleStr);
+
+ expectToBe(size, expectedSize);
+ });
+
+ it('... should load a huge number of triples into the rdfstore', async () => {
+ let tripleStr = '@prefix ex: . ';
+ const expectedSize = 1000;
+
+ for (let i = 0; i < expectedSize; i++) {
+ tripleStr += ` . `;
+ }
+
+ const size = await (graphVisualizerService as any)._loadTriplesInStore(store, tripleStr);
+
+ expectToBe(size, expectedSize);
+ });
+
+ it('... should load prefixed triples into the rdfstore', async () => {
+ const tripleStr =
+ '@prefix ex: . ' +
+ 'ex:subject ex:predicate ex:object. ' +
+ 'ex:subject2 ex:predicate2 ex:object2.';
+ const expectedSize = 2;
+
+ const size = await (graphVisualizerService as any)._loadTriplesInStore(store, tripleStr);
+
+ expectToBe(size, expectedSize);
+ });
+
+ it('... should load triples without prefixes or URIs into the rdfstore', async () => {
+ const tripleStr = '
}
{
EditionTkaTableStubComponent
) as EditionTkaTableStubComponent;
- expectToEqual(editionTkaTableCmp.textcriticalComments, expectedCorrections[index].comments);
+ expectToEqual(editionTkaTableCmp.textcriticalCommentBlocks, expectedCorrections[index].comments);
});
});
@@ -277,7 +277,11 @@ describe('SourceDescriptionCorrectionsComponent (DONE)', () => {
EditionTkaTableStubComponent
) as EditionTkaTableStubComponent;
- expect(editionTkaTableCmp.isRowTable).toBe(expectedCorrections[index].rowtable);
+ if (expectedCorrections[index].rowtable) {
+ expectToBe(editionTkaTableCmp.isRowTable, expectedCorrections[index].rowtable);
+ } else {
+ expect(editionTkaTableCmp.isRowTable).toBeUndefined();
+ }
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-corrections/source-description-corrections.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-corrections/source-description-corrections.component.ts
index fee336a59..0bc51b235 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-corrections/source-description-corrections.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-corrections/source-description-corrections.component.ts
@@ -2,6 +2,13 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from
import { Textcritics } from '@awg-views/edition-view/models';
+/**
+ * The SourceDescriptionCorrections component.
+ *
+ * It contains the source description corrections section
+ * of the critical report
+ * of the edition view of the app.
+ */
@Component({
selector: 'awg-source-description-corrections',
templateUrl: './source-description-corrections.component.html',
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-details/source-description-details.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-details/source-description-details.component.ts
index 7395bf040..a00514f00 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-details/source-description-details.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description-details/source-description-details.component.ts
@@ -1,5 +1,12 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
+/**
+ * The SourceDescriptionDetails component.
+ *
+ * It contains the source description details section
+ * of the critical report
+ * of the edition view of the app.
+ */
@Component({
selector: 'awg-source-description-details',
templateUrl: './source-description-details.component.html',
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description.component.spec.ts
index 8164453de..0e08a1b12 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-description/source-description.component.spec.ts
@@ -1683,13 +1683,13 @@ describe('SourceDescriptionComponent (DONE)', () => {
const result1 = component.getWritingMaterialFirmSign(variant);
- expect(result1).toEqual({ route: '', full: 'Not a known firm sign.', short: 'unknown' });
+ expectToEqual(result1, { route: '', full: 'Not a known firm sign.', short: 'unknown' });
variant = undefined;
const result2 = component.getWritingMaterialFirmSign(variant);
- expect(result2).toEqual({ route: '', full: 'Not a known firm sign.', short: 'unknown' });
+ expectToEqual(result2, { route: '', full: 'Not a known firm sign.', short: 'unknown' });
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.html
index 202cc8ce2..8915a091c 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.html
@@ -11,8 +11,8 @@
>[Die Quellenbewertung zum Editionskomplex
erscheint im Zusammenhang der
vollständigen Edition von in
- {{ editionRouteConstants.EDITION.short }} {{ editionComplex.series.short }}/{{
- editionComplex.section.short
+ {{ editionRouteConstants.EDITION.short }} {{ editionComplex.pubStatement.series.short }}/{{
+ editionComplex.pubStatement.section.short
}}.]
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.spec.ts
index 992e29740..0c6fc0020 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-evaluation/source-evaluation.component.spec.ts
@@ -17,9 +17,9 @@ import { mockEditionData } from '@testing/mock-data';
import { RouterLinkStubDirective } from '@testing/router-stubs';
import { CompileHtmlComponent } from '@awg-shared/compile-html';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
-import { EditionComplex, EditionSvgSheet, SourceEvaluationList } from '@awg-views/edition-view/models';
+import { EditionComplex, SourceEvaluationList } from '@awg-views/edition-view/models';
+import { EditionComplexesService } from '@awg-views/edition-view/services';
import { SourceEvaluationComponent } from './source-evaluation.component';
@@ -60,7 +60,7 @@ describe('SourceEvaluationComponent (DONE)', () => {
compDe = fixture.debugElement;
// Test data
- expectedEditionComplex = EDITION_COMPLEXES.OP25;
+ expectedEditionComplex = EditionComplexesService.getEditionComplexById('OP25');
expectedComplexId = 'testComplex1';
expectedNextComplexId = 'testComplex2';
expectedReportFragment = 'source_A';
@@ -223,7 +223,11 @@ describe('SourceEvaluationComponent (DONE)', () => {
const shortComplexSpan = mockDocument.createElement('span');
shortComplexSpan.innerHTML = expectedEditionComplex.complexId.short;
- const evaluationPlaceholder = `[Die Quellenbewertung zum Editionskomplex ${fullComplexSpan.textContent} erscheint im Zusammenhang der vollständigen Edition von ${shortComplexSpan.textContent} in ${expectedEditionRouteConstants.EDITION.short} ${expectedEditionComplex.series.short}/${expectedEditionComplex.section.short}.]`;
+ const awg = EDITION_ROUTE_CONSTANTS.EDITION.short;
+ const series = expectedEditionComplex.pubStatement.series.short;
+ const section = expectedEditionComplex.pubStatement.section.short;
+
+ const evaluationPlaceholder = `[Die Quellenbewertung zum Editionskomplex ${fullComplexSpan.textContent} erscheint im Zusammenhang der vollständigen Edition von ${shortComplexSpan.textContent} in ${awg} ${series}/${section}.]`;
expectToBe(pEl.textContent.trim(), evaluationPlaceholder);
}));
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.html
index 5b4266215..15e9df778 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.html
@@ -1,50 +1,56 @@
-
+ }
@if (utils.isNotEmptyArray(sourceListData.textSources)) {
{
});
describe('VIEW', () => {
- it('... should contain one table with table body (no text sources), but no rows (tr) yet', () => {
- const tableBodyDes = getAndExpectDebugElementByCss(compDe, 'table > tbody', 1, 1);
+ it('... should contain one div.card with with div.card-body, but no tables yet', () => {
+ const divCardBodyDes = getAndExpectDebugElementByCss(compDe, 'div.card > div.card-body', 1, 1);
- getAndExpectDebugElementByCss(tableBodyDes[0], 'tr', 0, 0);
+ getAndExpectDebugElementByCss(divCardBodyDes[0], 'table', 0, 0);
});
});
});
@@ -92,15 +92,24 @@ describe('SourceListComponent (DONE)', () => {
});
describe('VIEW', () => {
- it('... should contain one div.card', () => {
- getAndExpectDebugElementByCss(compDe, 'div.card', 1, 1);
- });
+ describe('... without any sources', () => {
+ beforeEach(() => {
+ expectedSourceListData = {
+ sources: [],
+ textSources: [],
+ };
+ component.sourceListData = expectedSourceListData;
+ detectChangesOnPush(fixture);
+ });
- it('... should contain one div.card-body in div.card', () => {
- getAndExpectDebugElementByCss(compDe, 'div.card > div.card-body', 1, 1);
+ it('... should contain no tables with in div.card-body', () => {
+ const divCardBodyDes = getAndExpectDebugElementByCss(compDe, 'div.card > div.card-body', 1, 1);
+
+ getAndExpectDebugElementByCss(divCardBodyDes[0], 'table', 0, 0);
+ });
});
- describe('... if text sources are not present', () => {
+ describe('... with only musical sources', () => {
it('... should contain one table with table body in div.card-body', () => {
getAndExpectDebugElementByCss(compDe, 'div.card-body > table > tbody', 1, 1);
});
@@ -127,7 +136,41 @@ describe('SourceListComponent (DONE)', () => {
});
});
- it('... should contain siglum link in header column (th)', () => {
+ it('... should contain siglum container span in header column (th)', () => {
+ const expectedSourcesLength = expectedSourceListData.sources.length;
+ const tableBodyDes = getAndExpectDebugElementByCss(compDe, 'table > tbody', 1, 1);
+
+ const rowDes = getAndExpectDebugElementByCss(
+ tableBodyDes[0],
+ 'tr',
+ expectedSourcesLength,
+ expectedSourcesLength
+ );
+
+ rowDes.forEach((rowDe, index) => {
+ const columnDes = getAndExpectDebugElementByCss(rowDe, 'th', 1, 1);
+
+ const containerDes = getAndExpectDebugElementByCss(
+ columnDes[0],
+ 'span.awg-source-list-siglum-container',
+ 1,
+ 1
+ );
+ const containerEl = containerDes[0].nativeElement;
+
+ const expectedSiglum =
+ expectedSourceListData.sources[index].siglum +
+ expectedSourceListData.sources[index].siglumAddendum;
+
+ if (expectedSourceListData.sources[index].missing) {
+ expectToBe(containerEl.textContent.trim(), `[${expectedSiglum}]`);
+ } else {
+ expectToBe(containerEl.textContent.trim(), expectedSiglum.trim());
+ }
+ });
+ });
+
+ it('... should contain siglum link as link text in header column (th)', () => {
expectedSourceListData.sources[2].missing = false;
component.sourceListData = expectedSourceListData;
@@ -143,8 +186,14 @@ describe('SourceListComponent (DONE)', () => {
rowDes.forEach((rowDe, index) => {
const columnDes = getAndExpectDebugElementByCss(rowDe, 'th', 1, 1);
+ const containerDes = getAndExpectDebugElementByCss(
+ columnDes[0],
+ 'span.awg-source-list-siglum-container',
+ 1,
+ 1
+ );
- const anchorDes = getAndExpectDebugElementByCss(columnDes[0], 'a', 1, 1);
+ const anchorDes = getAndExpectDebugElementByCss(containerDes[0], 'a', 1, 1);
const anchorEl = anchorDes[0].nativeElement;
const spanDes = getAndExpectDebugElementByCss(anchorDes[0], 'span', 1, 1);
@@ -160,7 +209,7 @@ describe('SourceListComponent (DONE)', () => {
});
});
- it('... should display siglum addendum if present in header column (th)', () => {
+ it('... should display siglum addendum as link text if present in header column (th)', () => {
expectedSourceListData.sources[0].siglumAddendum = 'a';
expectedSourceListData.sources[1].siglumAddendum = 'b';
expectedSourceListData.sources[2].siglumAddendum = 'H';
@@ -179,8 +228,14 @@ describe('SourceListComponent (DONE)', () => {
rowDes.forEach((rowDe, index) => {
const columnDes = getAndExpectDebugElementByCss(rowDe, 'th', 1, 1);
+ const containerDes = getAndExpectDebugElementByCss(
+ columnDes[0],
+ 'span.awg-source-list-siglum-container',
+ 1,
+ 1
+ );
- const anchorDes = getAndExpectDebugElementByCss(columnDes[0], 'a', 1, 1);
+ const anchorDes = getAndExpectDebugElementByCss(containerDes[0], 'a', 1, 1);
const anchorEl = anchorDes[0].nativeElement;
const spanDes = getAndExpectDebugElementByCss(anchorDes[0], 'span', 2, 2);
@@ -204,7 +259,7 @@ describe('SourceListComponent (DONE)', () => {
});
});
- it('... should display missing sources in brackets in header column (th)', () => {
+ it('... should display missing sources in brackets as link text in header column (th)', () => {
expectedSourceListData.sources[0].missing = true;
expectedSourceListData.sources[1].missing = true;
expectedSourceListData.sources[2].missing = true;
@@ -222,30 +277,42 @@ describe('SourceListComponent (DONE)', () => {
rowDes.forEach((rowDe, index) => {
const columnDes = getAndExpectDebugElementByCss(rowDe, 'th', 1, 1);
+ const containerDes = getAndExpectDebugElementByCss(
+ columnDes[0],
+ 'span.awg-source-list-siglum-container',
+ 1,
+ 1
+ );
- const anchorDes = getAndExpectDebugElementByCss(columnDes[0], 'a', 1, 1);
+ const anchorDes = getAndExpectDebugElementByCss(containerDes[0], 'a', 1, 1);
const anchorEl = anchorDes[0].nativeElement;
const spanDes = getAndExpectDebugElementByCss(anchorDes[0], 'span', 3, 3);
- // First span is opening bracket
- // Last span is closing bracket
+ const openingBracketDes = spanDes[0];
const siglumDes = spanDes[1];
+ const closingBracketDes = spanDes[2];
+
+ const openingBracketEl = openingBracketDes.nativeElement;
const siglumEl = siglumDes.nativeElement;
+ const closingBracketEl = closingBracketDes.nativeElement;
const expectedSiglum = expectedSourceListData.sources[index].siglum;
expectToBe(anchorEl.textContent.trim(), `[${expectedSiglum}]`);
+ expectToBe(openingBracketEl.textContent.trim(), '[');
+ expectToBe(closingBracketEl.textContent.trim(), ']');
+
expectToBe(siglumEl.textContent.trim(), expectedSiglum.trim());
expect(siglumEl).toHaveClass('awg-source-list-siglum');
});
});
- it('... should display missing sources with addendum in brackets in header column (th)', () => {
+ it('... should display missing sources with addendum in brackets as link text in header column (th)', () => {
expectedSourceListData.sources[0].siglumAddendum = 'a';
expectedSourceListData.sources[1].siglumAddendum = 'H';
- expectedSourceListData.sources[2].siglumAddendum = 'F1-2';
+ expectedSourceListData.sources[2].siglumAddendum = 'F1-F2';
expectedSourceListData.sources[0].missing = true;
expectedSourceListData.sources[1].missing = true;
@@ -264,25 +331,36 @@ describe('SourceListComponent (DONE)', () => {
rowDes.forEach((rowDe, index) => {
const columnDes = getAndExpectDebugElementByCss(rowDe, 'th', 1, 1);
+ const containerDes = getAndExpectDebugElementByCss(
+ columnDes[0],
+ 'span.awg-source-list-siglum-container',
+ 1,
+ 1
+ );
- const anchorDes = getAndExpectDebugElementByCss(columnDes[0], 'a', 1, 1);
+ const anchorDes = getAndExpectDebugElementByCss(containerDes[0], 'a', 1, 1);
const anchorEl = anchorDes[0].nativeElement;
const spanDes = getAndExpectDebugElementByCss(anchorDes[0], 'span', 4, 4);
- // First span is opening bracket
- // Last span is closing bracket
+ const openingBracketDes = spanDes[0];
const siglumDes = spanDes[1];
- const siglumEl = siglumDes.nativeElement;
-
const siglumAddendumDes = spanDes[2];
+ const closingBracketDes = spanDes[3];
+
+ const openingBracketEl = openingBracketDes.nativeElement;
+ const siglumEl = siglumDes.nativeElement;
const siglumAddendumEl = siglumAddendumDes.nativeElement;
+ const closingBracketEl = closingBracketDes.nativeElement;
const expectedSiglum = expectedSourceListData.sources[index].siglum;
const expectedAddendum = expectedSourceListData.sources[index].siglumAddendum;
expectToBe(anchorEl.textContent.trim(), `[${expectedSiglum}${expectedAddendum}]`);
+ expectToBe(openingBracketEl.textContent.trim(), '[');
+ expectToBe(closingBracketEl.textContent.trim(), ']');
+
expectToBe(siglumEl.textContent.trim(), expectedSiglum.trim());
expect(siglumEl).toHaveClass('awg-source-list-siglum');
@@ -291,6 +369,124 @@ describe('SourceListComponent (DONE)', () => {
});
});
+ it('... should contain link to report fragment for sources with description and linkTo value', fakeAsync(() => {
+ expectedSourceListData = {
+ sources: [
+ {
+ siglum: 'A',
+ siglumAddendum: '',
+ type: 'Test type 3',
+ location: 'Test location 3.',
+ hasDescription: true,
+ linkTo: 'source_A',
+ },
+ ],
+ };
+ component.sourceListData = expectedSourceListData;
+ detectChangesOnPush(fixture);
+
+ const expectedSourcesLength = expectedSourceListData.sources.length;
+ const tableBodyDes = getAndExpectDebugElementByCss(compDe, 'table > tbody', 1, 1);
+
+ const anchorDes = getAndExpectDebugElementByCss(
+ tableBodyDes[0],
+ 'tr > th > span.awg-source-list-siglum-container > a',
+ expectedSourcesLength,
+ expectedSourcesLength
+ );
+
+ clickAndAwaitChanges(anchorDes[0], fixture);
+
+ expectSpyCall(navigateToReportFragmentSpy, 1, { complexId: '', fragmentId: 'source_A' });
+ }));
+
+ it('... should contain link to openModal for sources without description but linkTo value', fakeAsync(() => {
+ expectedSourceListData = {
+ sources: [
+ {
+ siglum: 'B',
+ siglumAddendum: '',
+ type: 'Test type 3',
+ location: 'Test location 3.',
+ hasDescription: false,
+ linkTo: 'MODAL_TEXT',
+ },
+ ],
+ };
+ component.sourceListData = expectedSourceListData;
+ detectChangesOnPush(fixture);
+
+ const expectedSourcesLength = expectedSourceListData.sources.length;
+ const tableBodyDes = getAndExpectDebugElementByCss(compDe, 'table > tbody', 1, 1);
+
+ const anchorDes = getAndExpectDebugElementByCss(
+ tableBodyDes[0],
+ 'tr > th > span.awg-source-list-siglum-container > a',
+ expectedSourcesLength,
+ expectedSourcesLength
+ );
+
+ clickAndAwaitChanges(anchorDes[0], fixture);
+
+ expectSpyCall(openModalSpy, 1, 'MODAL_TEXT');
+ }));
+
+ it('... should contain no link for missing sources without description and linkTo value', () => {
+ expectedSourceListData = {
+ sources: [
+ {
+ siglum: 'C',
+ siglumAddendum: '',
+ missing: true,
+ type: 'Test type 3',
+ location: 'Test location 3.',
+ hasDescription: false,
+ linkTo: '',
+ },
+ ],
+ };
+ component.sourceListData = expectedSourceListData;
+ detectChangesOnPush(fixture);
+
+ const expectedSourcesLength = expectedSourceListData.sources.length;
+ const rowDes = getAndExpectDebugElementByCss(
+ compDe,
+ 'table > tbody > tr',
+ expectedSourcesLength,
+ expectedSourcesLength
+ );
+
+ rowDes.forEach((rowDe, index) => {
+ const columnDes = getAndExpectDebugElementByCss(rowDe, 'th', 1, 1);
+ const containerDes = getAndExpectDebugElementByCss(
+ columnDes[0],
+ 'span.awg-source-list-siglum-container',
+ 1,
+ 1
+ );
+
+ getAndExpectDebugElementByCss(containerDes[0], 'a', 0, 0);
+
+ const spanDes = getAndExpectDebugElementByCss(containerDes[0], 'span', 3, 3);
+
+ const openingBracketDes = spanDes[0];
+ const siglumDes = spanDes[1];
+ const closingBracketDes = spanDes[2];
+
+ const openingBracketEl = openingBracketDes.nativeElement;
+ const siglumEl = siglumDes.nativeElement;
+ const closingBracketEl = closingBracketDes.nativeElement;
+
+ const expectedSiglum = expectedSourceListData.sources[index].siglum;
+
+ expectToBe(openingBracketEl.textContent.trim(), '[');
+ expectToBe(closingBracketEl.textContent.trim(), ']');
+
+ expectToBe(siglumEl.textContent.trim(), expectedSiglum.trim());
+ expect(siglumEl).toHaveClass('awg-source-list-siglum');
+ });
+ });
+
it('... should contain source type and source location in second table column (td)', () => {
const expectedSourcesLength = expectedSourceListData.sources.length;
const rowDes = getAndExpectDebugElementByCss(
@@ -313,7 +509,7 @@ describe('SourceListComponent (DONE)', () => {
});
});
- describe('... if text sources are present', () => {
+ describe('... with musical and text sources', () => {
beforeEach(() => {
expectedSourceListData = JSON.parse(JSON.stringify(mockEditionData.mockSourceListDataWithTexts));
component.sourceListData = expectedSourceListData;
@@ -507,8 +703,15 @@ describe('SourceListComponent (DONE)', () => {
});
it('... should trigger on click', fakeAsync(() => {
- // Get anhors in description
- const anchorDes = getAndExpectDebugElementByCss(compDe, 'table tr > th > a', 3, 3);
+ const expectedSourcesLength = expectedSourceListData.sources.length;
+ const tableBodyDes = getAndExpectDebugElementByCss(compDe, 'table > tbody', 1, 1);
+
+ const anchorDes = getAndExpectDebugElementByCss(
+ tableBodyDes[0],
+ 'tr > th > span.awg-source-list-siglum-container > a',
+ expectedSourcesLength,
+ expectedSourcesLength
+ );
// Everything but first anchor uses modal
// Click on first anchor
@@ -578,8 +781,15 @@ describe('SourceListComponent (DONE)', () => {
});
it('... should trigger on click', fakeAsync(() => {
- // Get anhors in th column
- const anchorDes = getAndExpectDebugElementByCss(compDe, 'table tr > th > a', 3, 3);
+ const expectedSourcesLength = expectedSourceListData.sources.length;
+ const tableBodyDes = getAndExpectDebugElementByCss(compDe, 'table > tbody', 1, 1);
+
+ const anchorDes = getAndExpectDebugElementByCss(
+ tableBodyDes[0],
+ 'tr > th > span.awg-source-list-siglum-container > a',
+ expectedSourcesLength,
+ expectedSourcesLength
+ );
// Everything but first anchor uses modal
// Click on second anchor
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.ts
index a9846e430..b68edce74 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/source-list/source-list.component.ts
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
-import { UtilityService } from '@awg-app/core/services';
+import { UtilityService } from '@awg-core/services';
import { SourceList } from '@awg-views/edition-view/models';
/**
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html
index dcb8e2a07..a32792765 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html
@@ -16,39 +16,48 @@
- @if (utils.isNotEmptyArray(textcritics.description)) {
-
-
- :
-
+
+
+ :
+
+ @if (utils.isNotEmptyArray(textcritics.description)) {
-
- }
- @if (utils.isNotEmptyArray(textcritics.comments)) {
-
-
- :
-
+ } @else {
+
+ }
+
+
+
+ :
+
+ @if (utils.isNotEmptyArray(textcritics.comments)) {
-
- }
+ } @else {
+
+ }
+
+
+
+ [Nicht vorhanden.]
+
+
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts
index 8da113b90..635cccaf5 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts
@@ -16,9 +16,9 @@ import {
} from '@testing/expect-helper';
import { mockEditionData } from '@testing/mock-data';
-import { UtilityService } from '@awg-app/core/services';
+import { UtilityService } from '@awg-core/services';
import { CompileHtmlComponent } from '@awg-shared/compile-html';
-import { TextcriticalComment, TextcriticsList } from '@awg-views/edition-view/models';
+import { TextcriticalCommentBlock, TextcriticsList } from '@awg-views/edition-view/models';
import { TextcriticsListComponent } from './textcritics-list.component';
@@ -45,7 +45,7 @@ class EditionTkaLabelStubComponent {
@Component({ selector: 'awg-edition-tka-table', template: '' })
class EditionTkaTableStubComponent {
@Input()
- textcriticalComments: TextcriticalComment[];
+ textcriticalCommentBlocks: TextcriticalCommentBlock[];
@Input()
isCorrections = false;
@Input()
@@ -435,191 +435,284 @@ describe('TextcriticsListComponent (DONE)', () => {
detectChangesOnPush(fixture);
});
- it('... should contain no item body with div and paragraphs if description and comment arrays are empty', () => {
- const textcritics = expectedTextcriticsData.textcritics[0];
- const bodyDes = getAndExpectDebugElementByCss(
- compDe,
- `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
- 1,
- 1,
- 'open'
- );
-
- getAndExpectDebugElementByCss(bodyDes[0], 'div', 0, 0);
- });
-
- it('... should contain item body with div, small caps paragraph, first EditionTkaLabelComponent and EditionTkaDescriptionComponent if description array is not empty', () => {
- const textcritics = expectedTextcriticsData.textcritics[1];
-
- const bodyDes = getAndExpectDebugElementByCss(
- compDe,
- `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
- 1,
- 1,
- 'open'
- );
- const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
- const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
-
- getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
-
- getAndExpectDebugElementByDirective(divDes[0], EditionTkaDescriptionStubComponent, 1, 1);
- });
-
- it('... should pass down `id` data to first EditionTkaLabelComponent (stubbed)', () => {
- const bodyDes = getAndExpectDebugElementByCss(
- compDe,
- `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
- 1,
- 1,
- 'open'
- );
- const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
- const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
-
- const labelDes = getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
- const labelCmp = labelDes[0].injector.get(
- EditionTkaLabelStubComponent
- ) as EditionTkaLabelStubComponent;
-
- expectToBe(labelCmp.id, expectedTextcriticsData.textcritics[1].id);
- });
-
- it('... should pass down `labelType` data to first EditionTkaLabelComponent (stubbed)', () => {
- const bodyDes = getAndExpectDebugElementByCss(
- compDe,
- `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
- 1,
- 1,
- 'open'
- );
- const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
- const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
-
- const labelDes = getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
- const labelCmp = labelDes[0].injector.get(
- EditionTkaLabelStubComponent
- ) as EditionTkaLabelStubComponent;
-
- expectToBe(labelCmp.labelType, 'evaluation');
+ describe('... if description array is empty', () => {
+ it('... should contain item body with div, small caps paragraph, EditionTkaLabelComponent, but no EditionTkaDescriptionComponent', () => {
+ const textcritics = expectedTextcriticsData.textcritics[0];
+
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], EditionTkaDescriptionStubComponent, 0, 0);
+ });
+
+ it('... should display a no content message (small.text-muted) in another paragraph within item body div', () => {
+ const textcritics = expectedTextcriticsData.textcritics[0];
+
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p', 2, 2);
+
+ // Get small element of second paragraph
+ const smallDes = getAndExpectDebugElementByCss(pDes[1], 'small', 1, 1);
+ const smallEl = smallDes[0].nativeElement;
+
+ expectToContain(smallEl.textContent, '[Nicht vorhanden.]');
+ expect(smallEl).toHaveClass('text-muted');
+ });
});
- it('... should pass down `description` data to EditionTkaDescriptionComponent (stubbed)', () => {
- const editionTkaDescriptionDes = getAndExpectDebugElementByDirective(
- compDe,
- EditionTkaDescriptionStubComponent,
- 1,
- 1
- );
- const editionTkaDescriptionCmp = editionTkaDescriptionDes[0].injector.get(
- EditionTkaDescriptionStubComponent
- ) as EditionTkaDescriptionStubComponent;
-
- expectToEqual(
- editionTkaDescriptionCmp.textcriticalDescriptions,
- expectedTextcriticsData.textcritics[1].description
- );
+ describe('... if description array is not empty', () => {
+ it('... should contain item body with div, small caps paragraph, first EditionTkaLabelComponent and EditionTkaDescriptionComponent', () => {
+ const textcritics = expectedTextcriticsData.textcritics[1];
+
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], EditionTkaDescriptionStubComponent, 1, 1);
+ });
+
+ it('... should pass down `id` data to first EditionTkaLabelComponent (stubbed)', () => {
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ const labelDes = getAndExpectDebugElementByDirective(
+ pDes[0],
+ EditionTkaLabelStubComponent,
+ 1,
+ 1
+ );
+ const labelCmp = labelDes[0].injector.get(
+ EditionTkaLabelStubComponent
+ ) as EditionTkaLabelStubComponent;
+
+ expectToBe(labelCmp.id, expectedTextcriticsData.textcritics[1].id);
+ });
+
+ it('... should pass down `labelType` data to first EditionTkaLabelComponent (stubbed)', () => {
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:first-child', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ const labelDes = getAndExpectDebugElementByDirective(
+ pDes[0],
+ EditionTkaLabelStubComponent,
+ 1,
+ 1
+ );
+ const labelCmp = labelDes[0].injector.get(
+ EditionTkaLabelStubComponent
+ ) as EditionTkaLabelStubComponent;
+
+ expectToBe(labelCmp.labelType, 'evaluation');
+ });
+
+ it('... should pass down `description` data to EditionTkaDescriptionComponent (stubbed)', () => {
+ const editionTkaDescriptionDes = getAndExpectDebugElementByDirective(
+ compDe,
+ EditionTkaDescriptionStubComponent,
+ 1,
+ 1
+ );
+ const editionTkaDescriptionCmp = editionTkaDescriptionDes[0].injector.get(
+ EditionTkaDescriptionStubComponent
+ ) as EditionTkaDescriptionStubComponent;
+
+ expectToEqual(
+ editionTkaDescriptionCmp.textcriticalDescriptions,
+ expectedTextcriticsData.textcritics[1].description
+ );
+ });
});
- it('... should contain item body with div, small caps paragraph, second EditionTkaLabelComponent and EditionTkaTableComponent if comments array is not empty', () => {
- const textcritics = expectedTextcriticsData.textcritics[1];
-
- const bodyDes = getAndExpectDebugElementByCss(
- compDe,
- `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
- 1,
- 1,
- 'open'
- );
- const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
- const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
-
- getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
-
- getAndExpectDebugElementByDirective(divDes[0], EditionTkaTableStubComponent, 1, 1);
+ describe('... if commments array is empty', () => {
+ it('... should contain item body with div, small caps paragraph, EditionTkaLabelComponent, but no EditionTkaTableComponent', () => {
+ const textcritics = expectedTextcriticsData.textcritics[0];
+
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], EditionTkaTableStubComponent, 0, 0);
+ });
+
+ it('... should display a no content message (small.text-muted) in another paragraph within item body div', () => {
+ const textcritics = expectedTextcriticsData.textcritics[0];
+
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p', 2, 2);
+
+ // Get small element of second paragraph
+ const smallDes = getAndExpectDebugElementByCss(pDes[1], 'small', 1, 1);
+ const smallEl = smallDes[0].nativeElement;
+
+ expectToContain(smallEl.textContent, '[Nicht vorhanden.]');
+ expect(smallEl).toHaveClass('text-muted');
+ });
});
- it('... should pass down `id` data to second EditionTkaLabelComponent (stubbed)', () => {
- const bodyDes = getAndExpectDebugElementByCss(
- compDe,
- `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
- 1,
- 1,
- 'open'
- );
- const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
- const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
-
- const labelDes = getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
- const labelCmp = labelDes[0].injector.get(
- EditionTkaLabelStubComponent
- ) as EditionTkaLabelStubComponent;
-
- expectToBe(labelCmp.id, expectedTextcriticsData.textcritics[1].id);
- });
-
- it('... should pass down `labelType` data to second EditionTkaLabelComponent (stubbed)', () => {
- const bodyDes = getAndExpectDebugElementByCss(
- compDe,
- `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
- 1,
- 1,
- 'open'
- );
- const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
- const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
-
- const labelDes = getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
- const labelCmp = labelDes[0].injector.get(
- EditionTkaLabelStubComponent
- ) as EditionTkaLabelStubComponent;
-
- expectToBe(labelCmp.labelType, 'comment');
- });
-
- it('... should pass down `comments` to EditionTkaTableComponent (stubbed)', () => {
- const editionTkaTableDes = getAndExpectDebugElementByDirective(
- compDe,
- EditionTkaTableStubComponent,
- 1,
- 1
- );
- const editionTkaTableCmp = editionTkaTableDes[0].injector.get(
- EditionTkaTableStubComponent
- ) as EditionTkaTableStubComponent;
-
- expectToEqual(
- editionTkaTableCmp.textcriticalComments,
- expectedTextcriticsData.textcritics[1].comments
- );
- });
-
- it('... should pass down `isRowTable` to EditionTkaTableComponent (stubbed)', () => {
- const editionTkaTableDes = getAndExpectDebugElementByDirective(
- compDe,
- EditionTkaTableStubComponent,
- 1,
- 1
- );
- const editionTkaTableCmp = editionTkaTableDes[0].injector.get(
- EditionTkaTableStubComponent
- ) as EditionTkaTableStubComponent;
-
- expectToEqual(editionTkaTableCmp.isRowTable, expectedTextcriticsData.textcritics[1].rowtable);
- });
-
- it('... should pass down `isSketchId` to EditionTkaTableComponent (stubbed)', () => {
- const editionTkaTableDes = getAndExpectDebugElementByDirective(
- compDe,
- EditionTkaTableStubComponent,
- 1,
- 1
- );
- const editionTkaTableCmp = editionTkaTableDes[0].injector.get(
- EditionTkaTableStubComponent
- ) as EditionTkaTableStubComponent;
-
- expectToEqual(editionTkaTableCmp.isSketchId, false);
+ describe('... if comments array is not empty', () => {
+ it('... should contain item body with div, small caps paragraph, second EditionTkaLabelComponent and EditionTkaTableComponent', () => {
+ const textcritics = expectedTextcriticsData.textcritics[1];
+
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${textcritics.id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ getAndExpectDebugElementByDirective(pDes[0], EditionTkaLabelStubComponent, 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], EditionTkaTableStubComponent, 1, 1);
+ });
+
+ it('... should pass down `id` data to second EditionTkaLabelComponent (stubbed)', () => {
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ const labelDes = getAndExpectDebugElementByDirective(
+ pDes[0],
+ EditionTkaLabelStubComponent,
+ 1,
+ 1
+ );
+ const labelCmp = labelDes[0].injector.get(
+ EditionTkaLabelStubComponent
+ ) as EditionTkaLabelStubComponent;
+
+ expectToBe(labelCmp.id, expectedTextcriticsData.textcritics[1].id);
+ });
+
+ it('... should pass down `labelType` data to second EditionTkaLabelComponent (stubbed)', () => {
+ const bodyDes = getAndExpectDebugElementByCss(
+ compDe,
+ `div#${expectedTextcriticsData.textcritics[1].id} > div.accordion-collapse > div.accordion-body`,
+ 1,
+ 1,
+ 'open'
+ );
+ const divDes = getAndExpectDebugElementByCss(bodyDes[0], 'div:not(:first-child)', 1, 1);
+ const pDes = getAndExpectDebugElementByCss(divDes[0], 'p.smallcaps', 1, 1);
+
+ const labelDes = getAndExpectDebugElementByDirective(
+ pDes[0],
+ EditionTkaLabelStubComponent,
+ 1,
+ 1
+ );
+ const labelCmp = labelDes[0].injector.get(
+ EditionTkaLabelStubComponent
+ ) as EditionTkaLabelStubComponent;
+
+ expectToBe(labelCmp.labelType, 'comment');
+ });
+
+ it('... should pass down `comments` to EditionTkaTableComponent (stubbed)', () => {
+ const editionTkaTableDes = getAndExpectDebugElementByDirective(
+ compDe,
+ EditionTkaTableStubComponent,
+ 1,
+ 1
+ );
+ const editionTkaTableCmp = editionTkaTableDes[0].injector.get(
+ EditionTkaTableStubComponent
+ ) as EditionTkaTableStubComponent;
+
+ expectToEqual(
+ editionTkaTableCmp.textcriticalCommentBlocks,
+ expectedTextcriticsData.textcritics[1].comments
+ );
+ });
+
+ it('... should pass down `isRowTable` to EditionTkaTableComponent (stubbed)', () => {
+ const editionTkaTableDes = getAndExpectDebugElementByDirective(
+ compDe,
+ EditionTkaTableStubComponent,
+ 1,
+ 1
+ );
+ const editionTkaTableCmp = editionTkaTableDes[0].injector.get(
+ EditionTkaTableStubComponent
+ ) as EditionTkaTableStubComponent;
+
+ expectToEqual(editionTkaTableCmp.isRowTable, expectedTextcriticsData.textcritics[1].rowtable);
+ });
+
+ it('... should pass down `isSketchId` to EditionTkaTableComponent (stubbed)', () => {
+ const editionTkaTableDes = getAndExpectDebugElementByDirective(
+ compDe,
+ EditionTkaTableStubComponent,
+ 1,
+ 1
+ );
+ const editionTkaTableCmp = editionTkaTableDes[0].injector.get(
+ EditionTkaTableStubComponent
+ ) as EditionTkaTableStubComponent;
+
+ expectToEqual(editionTkaTableCmp.isSketchId, false);
+ });
});
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.html
index 4f2a72a56..b050e9b16 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.html
@@ -33,7 +33,7 @@
@if (selectedSvgSheet && selectedTextcritics) {
{
let expectedOverlays: EditionSvgOverlay[];
let expectedSvgSheet: EditionSvgSheet;
let expectedNextSvgSheet: EditionSvgSheet;
- let expectedSelectedTextcriticalComments: TextcriticalComment[];
+ let expectedSelectedTextcriticalCommentBlocks: TextcriticalCommentBlock[];
let expectedSelectedTextcritics: Textcritics;
let expectedShowTkA: boolean;
let expectedModalSnippet: string;
@@ -138,7 +138,7 @@ describe('EditionAccoladeComponent (DONE)', () => {
sheets: { workEditions: [], textEditions: [], sketchEditions: [expectedSvgSheet, expectedNextSvgSheet] },
};
expectedSelectedTextcritics = mockEditionData.mockTextcriticsData.textcritics.at(1);
- expectedSelectedTextcriticalComments = expectedSelectedTextcritics.comments;
+ expectedSelectedTextcriticalCommentBlocks = expectedSelectedTextcritics.comments;
const type = EditionSvgOverlayTypes.tka;
const id = 'tka-1';
@@ -184,8 +184,8 @@ describe('EditionAccoladeComponent (DONE)', () => {
expect(component.selectedSvgSheet).toBeUndefined();
});
- it('... should not have `selectedTextcriticalComments`', () => {
- expect(component.selectedTextcriticalComments).toBeUndefined();
+ it('... should not have `selectedTextcriticalCommentBlocks`', () => {
+ expect(component.selectedTextcriticalCommentBlocks).toBeUndefined();
});
it('... should not have `selectedTextcritics`', () => {
@@ -225,7 +225,7 @@ describe('EditionAccoladeComponent (DONE)', () => {
// Simulate the parent setting the input properties
component.svgSheetsData = expectedSvgSheetsData;
component.selectedSvgSheet = expectedSvgSheet;
- component.selectedTextcriticalComments = expectedSelectedTextcriticalComments;
+ component.selectedTextcriticalCommentBlocks = expectedSelectedTextcriticalCommentBlocks;
component.selectedTextcritics = expectedSelectedTextcritics;
component.showTkA = expectedShowTkA;
@@ -241,8 +241,8 @@ describe('EditionAccoladeComponent (DONE)', () => {
expectToEqual(component.selectedSvgSheet, expectedSvgSheet);
});
- it('... should have `selectedTextcriticalComments` input', () => {
- expectToEqual(component.selectedTextcriticalComments, expectedSelectedTextcriticalComments);
+ it('... should have `selectedTextcriticalCommentBlocks` input', () => {
+ expectToEqual(component.selectedTextcriticalCommentBlocks, expectedSelectedTextcriticalCommentBlocks);
});
it('... should have `selectedTextcritics` input', () => {
@@ -447,7 +447,7 @@ describe('EditionAccoladeComponent (DONE)', () => {
expectToEqual(footerCmp.selectedTextcritics, expectedSelectedTextcritics);
});
- it('... should pass down selectedTextcriticalComments to the EditionSvgSheetFooterComponent', () => {
+ it('... should pass down selectedTextcriticalCommentBlocks to the EditionSvgSheetFooterComponent', () => {
const footerDes = getAndExpectDebugElementByDirective(
compDe,
EditionSvgSheetFooterStubComponent,
@@ -458,7 +458,10 @@ describe('EditionAccoladeComponent (DONE)', () => {
EditionSvgSheetFooterStubComponent
) as EditionSvgSheetFooterStubComponent;
- expectToEqual(footerCmp.selectedTextcriticalComments, expectedSelectedTextcriticalComments);
+ expectToEqual(
+ footerCmp.selectedTextcriticalCommentBlocks,
+ expectedSelectedTextcriticalCommentBlocks
+ );
});
it('... should pass down showTkA to the EditionSvgSheetFooterComponent', () => {
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.ts
index 7bc514e92..843fa62c3 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-accolade.component.ts
@@ -4,7 +4,7 @@ import {
EditionSvgOverlay,
EditionSvgSheet,
EditionSvgSheetList,
- TextcriticalComment,
+ TextcriticalCommentBlock,
Textcritics,
} from '@awg-views/edition-view/models';
@@ -41,12 +41,12 @@ export class EditionAccoladeComponent {
selectedSvgSheet: EditionSvgSheet;
/**
- * Input variable: selectedTextcriticalComments.
+ * Input variable: selectedTextcriticalCommentBlocks.
*
- * It keeps the selected textcritical comments.
+ * It keeps the selected textcritical comment blocks.
*/
@Input()
- selectedTextcriticalComments: TextcriticalComment[];
+ selectedTextcriticalCommentBlocks: TextcriticalCommentBlock[];
/**
* Input variable: selectedTextcritics.
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.html
index e22b10cb5..af969f842 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.html
@@ -38,7 +38,7 @@
>:
{
let expectedSvgSheet: EditionSvgSheet;
let expectedNextSvgSheet: EditionSvgSheet;
let expectedSelectedTextcritics: Textcritics;
- let expectedSelectedTextcriticalComments: TextcriticalComment[];
+ let expectedSelectedTextcriticalCommentBlocks: TextcriticalCommentBlock[];
let expectedShowTka: boolean;
let expectedModalSnippet: string;
@@ -114,7 +114,7 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
expectedSvgSheet = JSON.parse(JSON.stringify(mockEditionData.mockSvgSheet_Sk1));
expectedNextSvgSheet = JSON.parse(JSON.stringify(mockEditionData.mockSvgSheet_Sk2));
expectedSelectedTextcritics = JSON.parse(JSON.stringify(mockEditionData.mockTextcriticsData.textcritics.at(1)));
- expectedSelectedTextcriticalComments = expectedSelectedTextcritics.comments;
+ expectedSelectedTextcriticalCommentBlocks = expectedSelectedTextcritics.comments;
expectedShowTka = true;
expectedChevronDownIcon = faChevronDown;
@@ -139,8 +139,8 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
});
describe('BEFORE initial data binding', () => {
- it('... should not have `selectedTextcriticalComments`', () => {
- expect(component.selectedTextcriticalComments).toBeUndefined();
+ it('... should not have `selectedTextcriticalCommentBlocks`', () => {
+ expect(component.selectedTextcriticalCommentBlocks).toBeUndefined();
});
it('... should not have `selectedTextcritics`', () => {
@@ -182,7 +182,7 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
beforeEach(() => {
// Simulate the parent setting the input properties
component.selectedTextcritics = expectedSelectedTextcritics;
- component.selectedTextcriticalComments = expectedSelectedTextcriticalComments;
+ component.selectedTextcriticalCommentBlocks = expectedSelectedTextcriticalCommentBlocks;
component.showTkA = expectedShowTka;
// Trigger initial data binding
@@ -193,8 +193,8 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
expectToEqual(component.selectedTextcritics, expectedSelectedTextcritics);
});
- it('... should have `selectedTextcriticalComments` input', () => {
- expectToEqual(component.selectedTextcriticalComments, expectedSelectedTextcriticalComments);
+ it('... should have `selectedTextcriticalCommentBlocks` input', () => {
+ expectToEqual(component.selectedTextcriticalCommentBlocks, expectedSelectedTextcriticalCommentBlocks);
});
it('... should have `showTkA` input', () => {
@@ -240,7 +240,7 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
expect(iconDe[0].children[0]).toBeTruthy();
expect(iconDe[0].children[0].classes).toBeTruthy();
- expect(iconDe[0].children[0].classes['fa-chevron-right']).toBeTrue();
+ expectToBe(iconDe[0].children[0].classes['fa-chevron-right'], true);
});
it('... should contain fa-icon with chevronDown in evaluation paragraph if showTextcritics = true', () => {
@@ -257,7 +257,7 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
expect(iconDe[0].children[0]).toBeTruthy();
expect(iconDe[0].children[0].classes).toBeTruthy();
- expect(iconDe[0].children[0].classes['fa-chevron-down']).toBeTrue();
+ expectToBe(iconDe[0].children[0].classes['fa-chevron-down'], true);
});
it('... should contain a span.smallcaps in evaluation paragraph with first EditionTkaLabelComponent', () => {
@@ -449,11 +449,11 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
expectToBe(labelCmp.labelType, 'comment');
});
- it('... should pass down `selectedTextcriticalComments` to the EditionTkaTableComponent', () => {
+ it('... should pass down `selectedTextcriticalCommentBlocks` to the EditionTkaTableComponent', () => {
const tableDes = getAndExpectDebugElementByDirective(compDe, EditionTkaTableStubComponent, 1, 1);
const tableCmp = tableDes[0].injector.get(EditionTkaTableStubComponent) as EditionTkaTableStubComponent;
- expectToEqual(tableCmp.textcriticalComments, expectedSelectedTextcriticalComments);
+ expectToEqual(tableCmp.textcriticalCommentBlocks, expectedSelectedTextcriticalCommentBlocks);
});
it('... should pass down `isRowTable` to the EditionTkaTableComponent', () => {
@@ -714,17 +714,17 @@ describe('EditionSvgSheetFooterComponent (DONE)', () => {
});
it('... should toggle `showTextcritics`', () => {
- expect(component.showTextcritics).toBe(false);
+ expectToBe(component.showTextcritics, false);
component.toggleTextcritics();
detectChangesOnPush(fixture);
- expect(component.showTextcritics).toBe(true);
+ expectToBe(component.showTextcritics, true);
component.toggleTextcritics();
detectChangesOnPush(fixture);
- expect(component.showTextcritics).toBe(false);
+ expectToBe(component.showTextcritics, false);
});
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.ts
index 2afb49e6d..ce49418c9 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-footer/edition-svg-sheet-footer.component.ts
@@ -2,8 +2,8 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from
import { faChevronDown, faChevronRight } from '@fortawesome/free-solid-svg-icons';
-import { UtilityService } from '@awg-app/core/services';
-import { TextcriticalComment, Textcritics } from '@awg-app/views/edition-view/models';
+import { UtilityService } from '@awg-core/services';
+import { TextcriticalCommentBlock, Textcritics } from '@awg-views/edition-view/models';
/**
* The EditionSvgSheetFooter component.
@@ -20,12 +20,12 @@ import { TextcriticalComment, Textcritics } from '@awg-app/views/edition-view/mo
})
export class EditionSvgSheetFooterComponent {
/**
- * Input variable: selectedTextcriticalComments.
+ * Input variable: selectedTextcriticalCommentBlocks.
*
- * It keeps the selected textcritical comments.
+ * It keeps the selected textcritical comment blocks.
*/
@Input()
- selectedTextcriticalComments: TextcriticalComment[];
+ selectedTextcriticalCommentBlocks: TextcriticalCommentBlock[];
/**
* Input variable: selectedTextcritics.
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts
index d2ca7d2a6..bffafe91b 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts
@@ -13,7 +13,7 @@ import {
} from '@testing/expect-helper';
import { mockEditionData } from '@testing/mock-data';
-import { EditionSvgSheet } from '@awg-app/views/edition-view/models';
+import { EditionSvgSheet } from '@awg-views/edition-view/models';
import { EditionSvgSheetNavItemComponent } from './edition-svg-sheet-nav-item.component';
@@ -176,10 +176,10 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
const anchorEl1 = anchorDes[1].nativeElement;
expectToContain(anchorEl0.classList, 'active');
- expect(anchorEl0.classList).withContext(`should not contain 'text-muted'`).not.toContain('text-muted');
+ expect(anchorEl0.classList).not.toContain('text-muted');
expectToContain(anchorEl1.classList, 'text-muted');
- expect(anchorEl1.classList).withContext(`should not contain 'active'`).not.toContain('active');
+ expect(anchorEl1.classList).not.toContain('active');
});
it('... should display sheet label in direct anchors (no partials)', () => {
@@ -289,7 +289,7 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
const anchorEl = anchorDe.nativeElement;
expectToContain(anchorEl.classList, 'text-muted');
- expect(anchorEl.classList).withContext(`should not contain 'active'`).not.toContain('active');
+ expect(anchorEl.classList).not.toContain('active');
});
});
@@ -307,10 +307,10 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
let anchorEl1 = anchorDes[1].nativeElement;
expectToContain(anchorEl0.classList, 'active');
- expect(anchorEl0.classList).withContext(`should not contain 'text-muted'`).not.toContain('text-muted');
+ expect(anchorEl0.classList).not.toContain('text-muted');
expectToContain(anchorEl1.classList, 'text-muted');
- expect(anchorEl1.classList).withContext(`should not contain 'active'`).not.toContain('active');
+ expect(anchorEl1.classList).not.toContain('active');
component.selectedSvgSheet = JSON.parse(JSON.stringify(mockEditionData.mockSvgSheet_Sk3b));
detectChangesOnPush(fixture);
@@ -325,10 +325,10 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
anchorEl1 = anchorDes[1].nativeElement;
expectToContain(anchorEl0.classList, 'text-muted');
- expect(anchorEl0.classList).withContext(`should not contain 'active'`).not.toContain('active');
+ expect(anchorEl0.classList).not.toContain('active');
expectToContain(anchorEl1.classList, 'active');
- expect(anchorEl1.classList).withContext(`should not contain 'text-muted'`).not.toContain('text-muted');
+ expect(anchorEl1.classList).not.toContain('text-muted');
});
it('... should have as many item anchors (.dropdown-item) in dropdown as partials in sheet content', () => {
@@ -364,12 +364,10 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
const anchorEl1 = anchorDes[1].nativeElement;
expectToContain(anchorEl0.classList, 'active');
- expect(anchorEl0.classList)
- .withContext(`should not have class 'text-muted'`)
- .not.toContain('text-muted');
+ expect(anchorEl0.classList).not.toContain('text-muted');
expectToContain(anchorEl1.classList, 'text-muted');
- expect(anchorEl1.classList).withContext(`should not have class 'active'`).not.toContain('active');
+ expect(anchorEl1.classList).not.toContain('active');
});
it('... should display sheet labels in dropdown item anchors (with numbered partials)', () => {
@@ -408,13 +406,13 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
it('... should return false if given id does not equal id of selected svg sheet', () => {
const comparison = component.isSelectedSvgSheet(expectedNextSvgSheet.id);
- expect(comparison).toBeFalse();
+ expectToBe(comparison, false);
});
it('... should return true if given id does equal id of selected svg sheet', () => {
const comparison = component.isSelectedSvgSheet(expectedSvgSheet.id);
- expect(comparison).toBeTrue();
+ expectToBe(comparison, true);
});
});
@@ -425,7 +423,7 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
const comparison = component.isSelectedSvgSheet(expectedSvgSheetWithPartials.id, 'XXX');
- expect(comparison).toBeFalse();
+ expectToBe(comparison, false);
});
it('... should return true if given id does equal id with partial of selected svg sheet', () => {
@@ -434,7 +432,7 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => {
const comparison = component.isSelectedSvgSheet(expectedSvgSheetWithPartials.id, 'a');
- expect(comparison).toBeTrue();
+ expectToBe(comparison, true);
});
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts
index 32317529d..73fee9a71 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts
@@ -1,6 +1,7 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { UtilityService } from '@awg-app/core/services';
-import { EditionSvgSheet } from '@awg-app/views/edition-view/models';
+
+import { UtilityService } from '@awg-core/services';
+import { EditionSvgSheet } from '@awg-views/edition-view/models';
/**
* The EditionSvgSheetNavItem component.
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-viewer/edition-svg-sheet-viewer.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-viewer/edition-svg-sheet-viewer.component.spec.ts
index 091a75efd..74495ab91 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-viewer/edition-svg-sheet-viewer.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-viewer/edition-svg-sheet-viewer.component.spec.ts
@@ -12,6 +12,7 @@ import { clickAndAwaitChanges } from '@testing/click-helper';
import {
expectSpyCall,
expectToBe,
+ expectToContain,
expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
@@ -216,7 +217,7 @@ describe('EditionSvgSheetViewerComponent', () => {
it('... injected service should use provided mockValue', () => {
const svgDrawingService = TestBed.inject(EditionSvgDrawingService);
- expect(svgDrawingService === mockEditionSvgDrawingService).toBe(true);
+ expectToBe(svgDrawingService === mockEditionSvgDrawingService, true);
});
describe('BEFORE initial data binding', () => {
@@ -414,9 +415,9 @@ describe('EditionSvgSheetViewerComponent', () => {
expectToBe(buttonEl.getAttribute('title'), 'Reset zoom');
expectToBe(buttonEl.getAttribute('type'), 'submit');
- expect(buttonEl.classList).toContain('btn');
- expect(buttonEl.classList).toContain('btn-sm');
- expect(buttonEl.classList).toContain('btn-outline-info');
+ expectToContain(buttonEl.classList, 'btn');
+ expectToContain(buttonEl.classList, 'btn-sm');
+ expectToContain(buttonEl.classList, 'btn-outline-info');
});
it('... should display compress icon in button', () => {
@@ -739,11 +740,13 @@ describe('EditionSvgSheetViewerComponent', () => {
const overlayGroupRectSelection = expectedOverlayGroups.select(
`#${overlay.id} rect.${expectedOverlayType}`
);
- expect(serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[0]).toEqual(overlay);
- expect(serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[1]).toEqual(
+ expectToEqual(serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[0], overlay);
+ expectToEqual(
+ serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[1],
overlayGroupRectSelection
);
- expect(serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[2]).toEqual(
+ expectToBe(
+ serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[2],
EditionSvgOverlayActionTypes.fill
);
});
@@ -758,7 +761,8 @@ describe('EditionSvgSheetViewerComponent', () => {
expect(serviceUpdateTkkOverlayColorSpy).toHaveBeenCalledTimes(expectedOverlayGroups.nodes().length);
expectedOverlayGroups.nodes().forEach((_node, index) => {
- expect(serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[2]).toEqual(
+ expectToBe(
+ serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[2],
EditionSvgOverlayActionTypes.fill
);
});
@@ -773,7 +777,8 @@ describe('EditionSvgSheetViewerComponent', () => {
expect(serviceUpdateTkkOverlayColorSpy).toHaveBeenCalledTimes(expectedOverlayGroups.nodes().length);
expectedOverlayGroups.nodes().forEach((_node, index) => {
- expect(serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[2]).toEqual(
+ expectToBe(
+ serviceUpdateTkkOverlayColorSpy.calls.all()[index].args[2],
EditionSvgOverlayActionTypes.transparent
);
});
@@ -815,17 +820,17 @@ describe('EditionSvgSheetViewerComponent', () => {
let expectedZoom = null;
component.onZoomChange(expectedZoom);
- expect(component.sliderConfig.value).toBe(expectedZoom);
+ expectToBe(component.sliderConfig.value, expectedZoom);
expectedZoom = 5;
component.onZoomChange(expectedZoom);
- expect(component.sliderConfig.value).toBe(expectedZoom);
+ expectToBe(component.sliderConfig.value, expectedZoom);
expectedZoom = expectedSliderConfig.initial;
component.onZoomChange(expectedZoom);
- expect(component.sliderConfig.value).toBe(expectedSliderConfig.initial);
+ expectToBe(component.sliderConfig.value, expectedSliderConfig.initial);
});
it('... should trigger `_rescaleZoom` function', () => {
@@ -1363,7 +1368,7 @@ describe('EditionSvgSheetViewerComponent', () => {
it(`... for stepSize ${stepSize} and given value ${givenValue} returns ${expectedNearestStep}`, () => {
component.sliderConfig.stepSize = stepSize;
const result = (component as any)._roundToScaleStepDecimalPrecision(givenValue);
- expect(result).toBe(expectedNearestStep);
+ expectToBe(result, expectedNearestStep);
});
}
}
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-convolute.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-convolute.component.spec.ts
index d74623d07..ca247b37a 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-convolute.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-convolute.component.spec.ts
@@ -127,7 +127,7 @@ describe('EditionConvoluteComponent (DONE)', () => {
});
it('... should have faSquare', () => {
- expectToBe(component.faSquare, faSquare);
+ expectToEqual(component.faSquare, faSquare);
});
it('... should have folioLegends', () => {
@@ -402,7 +402,7 @@ describe('EditionConvoluteComponent (DONE)', () => {
const reportLinkDe = linkDes[0]; // Contact link DebugElement
const reportLink = routerLinks[0]; // Contact link directive
- expect(reportLink.navigatedTo).toBeNull();
+ expectToBe(reportLink.navigatedTo, null);
click(reportLinkDe);
fixture.detectChanges();
@@ -414,7 +414,7 @@ describe('EditionConvoluteComponent (DONE)', () => {
const reportLinkDe = linkDes[0]; // Contact link DebugElement
const reportLink = routerLinks[0]; // Contact link directive
- expect(reportLink.navigatedTo).toBeNull();
+ expectToBe(reportLink.navigatedTo, null);
click(reportLinkDe);
fixture.detectChanges();
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/edition-folio-viewer.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/edition-folio-viewer.component.spec.ts
index f8312f815..9d0b9ab81 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/edition-folio-viewer.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/edition-folio-viewer.component.spec.ts
@@ -7,7 +7,13 @@ import Spy = jasmine.Spy;
import { cleanStylesFromDOM } from '@testing/clean-up-helper';
import { clickAndAwaitChanges } from '@testing/click-helper';
-import { expectSpyCall, expectToBe, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper';
+import {
+ expectSpyCall,
+ expectToBe,
+ expectToContain,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+} from '@testing/expect-helper';
import { mockEditionData } from '@testing/mock-data';
import {
@@ -141,7 +147,7 @@ describe('EditionFolioViewerComponent (DONE)', () => {
it('... injected service should use provided mockValue', () => {
const folioService = TestBed.inject(FolioService);
- expect(mockFolioService === folioService).toBeTrue();
+ expectToBe(mockFolioService === folioService, true);
});
describe('BEFORE initial data binding', () => {
@@ -236,8 +242,8 @@ describe('EditionFolioViewerComponent (DONE)', () => {
const expectedLgColClass = 'col-lg-' + Math.floor(12 / expectedFolioSvgDataArray.length);
- expect(colEl.classList.contains('col-sm-6')).toBeTrue();
- expect(colEl.classList.contains(expectedLgColClass)).toBeTrue();
+ expectToContain(colEl.classList, 'col-sm-6');
+ expectToContain(colEl.classList, expectedLgColClass);
});
});
@@ -377,8 +383,10 @@ describe('EditionFolioViewerComponent (DONE)', () => {
component.createSVGCanvas();
expect(component.viewBoxArray.length).not.toEqual(component.folioSvgDataArray.length);
- expectToEqual(component.canvasArray, []);
expectToBe(component.canvasArray.length, 0);
+ expectToBe(component.viewBoxArray.length, 2);
+
+ expectToEqual(component.canvasArray, []);
});
it('... svgCanvas is empty', () => {
@@ -387,7 +395,7 @@ describe('EditionFolioViewerComponent (DONE)', () => {
component.prepareFolioSvgOutput();
component.createSVGCanvas();
- expect(component.canvasArray).toEqual([]);
+ expectToEqual(component.canvasArray, []);
});
});
@@ -451,13 +459,13 @@ describe('EditionFolioViewerComponent (DONE)', () => {
it('... the given id matches the selectedSvgSheet id', () => {
component.selectedSvgSheet = expectedSvgSheet;
- expect(component.isSelectedSvgSheet('test-1')).toBeTrue();
+ expectToBe(component.isSelectedSvgSheet('test-1'), true);
});
it('... the given id matches the selectedSvgSheet id with partial', () => {
component.selectedSvgSheet = expectedSvgSheetWithPartialA;
- expect(component.isSelectedSvgSheet('test-2a')).toBeTrue();
+ expectToBe(component.isSelectedSvgSheet('test-2a'), true);
});
});
@@ -465,19 +473,19 @@ describe('EditionFolioViewerComponent (DONE)', () => {
it('... the given id does not match the selectedSvgSheet id', () => {
component.selectedSvgSheet = expectedSvgSheet;
- expect(component.isSelectedSvgSheet('other-test')).toBeFalse();
+ expectToBe(component.isSelectedSvgSheet('other-test'), false);
});
it('... given the id does not match the selectedSvgSheet id with partial', () => {
component.selectedSvgSheet = expectedSvgSheetWithPartialA;
- expect(component.isSelectedSvgSheet('test-2b')).toBeFalse();
+ expectToBe(component.isSelectedSvgSheet('test-2b'), false);
});
it('... selectedSvgSheet is undefined', () => {
component.selectedSvgSheet = undefined;
- expect(component.isSelectedSvgSheet('test-1')).toBeFalse();
+ expectToBe(component.isSelectedSvgSheet('test-1'), false);
});
});
});
@@ -730,15 +738,15 @@ describe('EditionFolioViewerComponent (DONE)', () => {
component.toggleActiveClass();
- expect(svgGroupSelection1.classed('active')).toBe(true);
- expect(svgGroupSelection2.classed('active')).toBe(false);
+ expectToBe(svgGroupSelection1.classed('active'), true);
+ expectToBe(svgGroupSelection2.classed('active'), false);
isSelectedSvgSheetSpy.and.callFake(contentSegmentId => contentSegmentId === 'another-id');
component.toggleActiveClass();
- expect(svgGroupSelection1.classed('active')).toBe(false);
- expect(svgGroupSelection2.classed('active')).toBe(true);
+ expectToBe(svgGroupSelection1.classed('active'), false);
+ expectToBe(svgGroupSelection2.classed('active'), true);
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/folio.service.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/folio.service.spec.ts
index db422fb40..c51296e71 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/folio.service.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-convolute/edition-folio-viewer/folio.service.spec.ts
@@ -17,7 +17,7 @@ import {
FolioSvgContentSegment,
FolioSvgData,
ViewBox,
-} from '@awg-app/views/edition-view/models';
+} from '@awg-views/edition-view/models';
import { mockConsole } from '@testing/mock-helper';
import { FolioService } from './folio.service';
@@ -48,6 +48,7 @@ describe('FolioService (DONE)', () => {
let expectedConvolutes: FolioConvolute[];
let expectedFolioSettings: FolioSettings;
let expectedFolioSvgData: FolioSvgData;
+ let expectedDefaultFolio: Folio;
let expectedReversedFolio: Folio;
let expectedUpperLeftCorner: FolioCalculationPoint;
@@ -81,6 +82,7 @@ describe('FolioService (DONE)', () => {
// Test data
expectedConvolutes = JSON.parse(JSON.stringify(mockEditionData.mockFolioConvoluteData.convolutes));
+ expectedDefaultFolio = expectedConvolutes[0].folios[0];
expectedReversedFolio = JSON.parse(JSON.stringify(mockEditionData.mockReversedFolio));
expectedFolioSettings = {
factor: 1.5,
@@ -109,11 +111,7 @@ describe('FolioService (DONE)', () => {
expectedLowerRightCorner = new FolioCalculationPoint(30, 40);
expectedFolioSvgData = new FolioSvgData(
- new FolioCalculation(
- expectedFolioSettings,
- expectedConvolutes[0].folios[0],
- expectedContentSegmentOffsetCorrection
- )
+ new FolioCalculation(expectedFolioSettings, expectedDefaultFolio, expectedContentSegmentOffsetCorrection)
);
// Spies on service functions
@@ -181,7 +179,7 @@ describe('FolioService (DONE)', () => {
it('... should use mock console', () => {
console.error('Test');
- expect(mockConsole.get(0)).toBe('Test');
+ expectToBe(mockConsole.get(0), 'Test');
});
it('... should clear mock console after each run', () => {
@@ -257,7 +255,7 @@ describe('FolioService (DONE)', () => {
it('... should return an instance of FolioSvgData object', () => {
// Create mock FolioSettings and Folio objects
const folioSettings: FolioSettings = expectedFolioSettings;
- const folio: Folio = expectedConvolutes[0].folios[0];
+ const folio: Folio = expectedDefaultFolio;
// Call the method with the mock objects
const result = folioService.getFolioSvgData(folioSettings, folio);
@@ -269,8 +267,7 @@ describe('FolioService (DONE)', () => {
it('... should create a new FolioCalculation object with the correct parameters', () => {
// Create mock FolioSettings and Folio objects
const folioSettings: FolioSettings = expectedFolioSettings;
- const folio: Folio = expectedConvolutes[0].folios[0];
-
+ const folio: Folio = expectedDefaultFolio;
const result = folioService.getFolioSvgData(folioSettings, folio);
expectToEqual(result, expectedFolioSvgData);
@@ -279,7 +276,7 @@ describe('FolioService (DONE)', () => {
it('... should create a new FolioCalculation object when contentSegmentOffsetCorrection is undefined', () => {
// Create mock FolioSettings and Folio objects
const folioSettings: FolioSettings = expectedFolioSettings;
- const folio: Folio = expectedConvolutes[0].folios[0];
+ const folio: Folio = expectedDefaultFolio;
const expectedFolioSvgDataWithoutOffset = new FolioSvgData(new FolioCalculation(folioSettings, folio, 0));
@@ -373,7 +370,7 @@ describe('FolioService (DONE)', () => {
});
it('should set the ref variable', () => {
- expect(folioService.ref).toBe(ref);
+ expectToEqual(folioService.ref, ref);
});
it('... should trigger `_appendCanvasSheetGroup` method', () => {
@@ -382,7 +379,7 @@ describe('FolioService (DONE)', () => {
it('should append one SVG sheet group to the svg canvas', () => {
expect(svgSheetGroup).toBeDefined();
- expect(svgSheetGroup.size()).toBe(1);
+ expectToBe(svgSheetGroup.size(), 1);
});
it('... should trigger `_addFolioSheetToSvgCanvas` method', () => {
@@ -859,7 +856,7 @@ describe('FolioService (DONE)', () => {
const sheetGroup = svgCanvas.select('g.sheet-group');
expect(sheetGroup).toBeDefined();
- expect(sheetGroup.size()).toBe(1);
+ expectToBe(sheetGroup.size(), 1);
});
it('... should set the `sheetGroupId` attribute of the sheet group', () => {
@@ -1372,8 +1369,8 @@ describe('FolioService (DONE)', () => {
const callArgs = appendSvgElementWithAttrsSpy.calls.argsFor(i);
const expectedArgs = [...commonArgs, i === 0 ? {} : additionalAttributes];
- expect(callArgs.length).toBe(expectedArgs.length);
- expect(callArgs).toEqual(expectedArgs);
+ expectToBe(callArgs.length, expectedArgs.length);
+ expectToEqual(callArgs, expectedArgs);
});
});
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.html
index 607023861..b08deaa0b 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.html
@@ -3,30 +3,40 @@
-
-
+
+ @if (isLoading) {
+
+ } @else {
+
+ @if (errorObject) {
+
+ } @else {
+
+
+
+
-
-
-
-
- @if (selectedConvolute && selectedSvgSheet) {
-
-
+
+ @if (selectedConvolute && selectedSvgSheet) {
+
+
+ }
+
+ }
}
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.spec.ts
index 50f2cdae1..2b1957a68 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.spec.ts
@@ -1,20 +1,23 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
+import { JsonPipe } from '@angular/common';
import { Component, DebugElement, EventEmitter, Input, Output } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
-import { Observable, of as observableOf } from 'rxjs';
+import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs';
import Spy = jasmine.Spy;
-import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
-
-import { expectSpyCall, expectToEqual, getAndExpectDebugElementByDirective } from '@testing/expect-helper';
+import {
+ expectSpyCall,
+ expectToBe,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+ getAndExpectDebugElementByDirective,
+} from '@testing/expect-helper';
import { mockEditionData } from '@testing/mock-data';
import { ActivatedRouteStub, UrlSegmentStub } from '@testing/router-stubs';
import { CompileHtmlComponent } from '@awg-shared/compile-html';
-import { ModalComponent } from '@awg-shared/modal/modal.component';
-import { EDITION_COMPLEXES } from '@awg-views/edition-view/data';
import { EDITION_ROUTE_CONSTANTS } from '@awg-views/edition-view/edition-route-constants';
import {
EditionComplex,
@@ -23,12 +26,18 @@ import {
EditionSvgSheetList,
FolioConvolute,
FolioConvoluteList,
- TextcriticalComment,
+ TextcriticalCommentBlock,
Textcritics,
TextcriticsList,
} from '@awg-views/edition-view/models';
-import { EditionDataService, EditionService, EditionSheetsService } from '@awg-views/edition-view/services';
+import {
+ EditionComplexesService,
+ EditionDataService,
+ EditionService,
+ EditionSheetsService,
+} from '@awg-views/edition-view/services';
+import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
import { EditionSheetsComponent } from './edition-sheets.component';
@Component({ selector: 'awg-edition-accolade', template: '' })
@@ -38,7 +47,7 @@ class EditionAccoladeStubComponent {
@Input()
selectedSvgSheet: EditionSvgSheet;
@Input()
- selectedTextcriticalComments: TextcriticalComment[];
+ selectedTextcriticalCommentBlocks: TextcriticalCommentBlock[];
@Input()
selectedTextcritics: Textcritics;
@Input()
@@ -69,6 +78,22 @@ class EditionConvoluteStubComponent {
selectSvgSheetRequest: EventEmitter<{ complexId: string; sheetId: string }> = new EventEmitter();
}
+@Component({ selector: 'awg-error-alert', template: '' })
+class ErrorAlertStubComponent {
+ @Input()
+ errorObject: any;
+}
+
+@Component({ selector: 'awg-modal', template: '' })
+class ModalStubComponent {
+ modalContent: string;
+ open(modalContentSnippetKey: string): void {
+ this.modalContent = modalContentSnippetKey;
+ }
+}
+@Component({ selector: 'awg-twelve-tone-spinner', template: '' })
+class TwelveToneSpinnerStubComponent {}
+
describe('EditionSheetsComponent', () => {
let component: EditionSheetsComponent;
let fixture: ComponentFixture;
@@ -84,7 +109,7 @@ describe('EditionSheetsComponent', () => {
let mockEditionSheetsService: Partial;
let editionDataServiceGetEditionSheetsDataSpy: Spy;
- let editionServiceGetEditionComplexSpy: Spy;
+ let editionServiceGetSelectedEditionComplexSpy: Spy;
let editionSheetsServiceSelectSvgSheetByIdSpy: Spy;
let editionSheetsServiceSelectConvoluteSpy: Spy;
let getEditionSheetsDataSpy: Spy;
@@ -92,6 +117,7 @@ describe('EditionSheetsComponent', () => {
let navigateWithComplexIdSpy: Spy;
let navigationSpy: Spy;
let onSvgSheetSelectSpy: Spy;
+ let selectSvgSheetSpy: Spy;
let expectedEditionComplex: EditionComplex;
let expectedFolioConvoluteData: FolioConvoluteList;
@@ -106,6 +132,12 @@ describe('EditionSheetsComponent', () => {
let expectedReportFragment: string;
const expectedEditionRouteConstants: typeof EDITION_ROUTE_CONSTANTS = EDITION_ROUTE_CONSTANTS;
+ const jsonPipe = new JsonPipe();
+
+ beforeAll(() => {
+ EditionComplexesService.initializeEditionComplexesList();
+ });
+
beforeEach(waitForAsync(() => {
// Mock router with spy object
// Router spy object
@@ -131,7 +163,7 @@ describe('EditionSheetsComponent', () => {
): Observable<(FolioConvoluteList | EditionSvgSheetList | TextcriticsList)[]> => observableOf([]),
};
mockEditionService = {
- getEditionComplex: (): Observable => observableOf(),
+ getSelectedEditionComplex: (): Observable => observableOf(),
};
mockEditionSheetsService = {
selectSvgSheetById: (sheets: EditionSvgSheetList['sheets'], id: string): EditionSvgSheet =>
@@ -144,13 +176,14 @@ describe('EditionSheetsComponent', () => {
};
TestBed.configureTestingModule({
- imports: [NgbModalModule],
declarations: [
CompileHtmlComponent,
EditionSheetsComponent,
EditionConvoluteStubComponent,
EditionAccoladeStubComponent,
- ModalComponent,
+ ErrorAlertStubComponent,
+ ModalStubComponent,
+ TwelveToneSpinnerStubComponent,
],
providers: [
{ provide: EditionDataService, useValue: mockEditionDataService },
@@ -172,7 +205,7 @@ describe('EditionSheetsComponent', () => {
mockActivatedRoute.testQueryParamMap = { id: '' };
// Test data
- expectedEditionComplex = EDITION_COMPLEXES.OP12;
+ expectedEditionComplex = EditionComplexesService.getEditionComplexById('OP12');
expectedComplexId = 'op12';
expectedNextComplexId = 'testComplex2';
expectedEditionComplexBaseRoute = `/edition/complex/${expectedComplexId}/`;
@@ -192,9 +225,10 @@ describe('EditionSheetsComponent', () => {
mockEditionDataService,
'getEditionSheetsData'
).and.returnValue(observableOf([expectedFolioConvoluteData, expectedSvgSheetsData, expectedTextcriticsData]));
- editionServiceGetEditionComplexSpy = spyOn(mockEditionService, 'getEditionComplex').and.returnValue(
- observableOf(expectedEditionComplex)
- );
+ editionServiceGetSelectedEditionComplexSpy = spyOn(
+ mockEditionService,
+ 'getSelectedEditionComplex'
+ ).and.returnValue(observableOf(expectedEditionComplex));
editionSheetsServiceSelectSvgSheetByIdSpy = spyOn(
mockEditionSheetsService,
'selectSvgSheetById'
@@ -202,11 +236,15 @@ describe('EditionSheetsComponent', () => {
editionSheetsServiceSelectConvoluteSpy = spyOn(mockEditionSheetsService, 'selectConvolute').and.returnValue(
expectedFolioConvoluteData[0]
);
+
+ navigationSpy = mockRouter.navigate as jasmine.Spy;
+
getEditionSheetsDataSpy = spyOn(component, 'getEditionSheetsData').and.callThrough();
navigateToReportFragmentSpy = spyOn(component, 'onReportFragmentNavigate').and.callThrough();
- navigateWithComplexIdSpy = spyOn(component as any, '_navigateWithComplexId').and.callThrough();
- navigationSpy = mockRouter.navigate as jasmine.Spy;
onSvgSheetSelectSpy = spyOn(component, 'onSvgSheetSelect').and.callThrough();
+
+ navigateWithComplexIdSpy = spyOn(component as any, '_navigateWithComplexId').and.callThrough();
+ selectSvgSheetSpy = spyOn(component as any, '_selectSvgSheet').and.callThrough();
});
it('... should create', () => {
@@ -218,8 +256,12 @@ describe('EditionSheetsComponent', () => {
expect(component.editionComplex).toBeUndefined();
});
- it('... should not have `errorMessage`', () => {
- expect(component.errorMessage).toBeUndefined();
+ it('... should have `errorObject` = null', () => {
+ expectToBe(component.errorObject, null);
+ });
+
+ it('... should have `isLoading===true`', () => {
+ expectToBe(component.isLoading, true);
});
it('... should not have `folioConvoluteData`', () => {
@@ -234,8 +276,8 @@ describe('EditionSheetsComponent', () => {
expect(component.selectedSvgSheet).toBeUndefined();
});
- it('... should not have `selectedTextcriticalComments`', () => {
- expect(component.selectedTextcriticalComments).toBeUndefined();
+ it('... should not have `selectedTextcriticalCommentBlocks`', () => {
+ expect(component.selectedTextcriticalCommentBlocks).toBeUndefined();
});
it('... should not have `selectedTextcritics`', () => {
@@ -243,7 +285,7 @@ describe('EditionSheetsComponent', () => {
});
it('... should have `showTkA===false`', () => {
- expect(component.showTkA).toBeFalse();
+ expectToBe(component.showTkA, false);
});
it('... should not have `snapshotQueryParamsId`', () => {
@@ -259,12 +301,44 @@ describe('EditionSheetsComponent', () => {
});
it('... should have `_isFirstPageLoad===true`', () => {
- expect((component as any)._isFirstPageLoad).toBeTrue();
+ expectToBe((component as any)._isFirstPageLoad, true);
});
it('... should have `editionRouteConstants` getter', () => {
expectToEqual(component.editionRouteConstants, expectedEditionRouteConstants);
});
+
+ describe('VIEW', () => {
+ it('... should contain a `div`', () => {
+ getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+ });
+
+ it('... should contain one modal component (stubbed)', () => {
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], ModalStubComponent, 1, 1);
+ });
+
+ it('... should not contain an error alert component (stubbed)', () => {
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], ErrorAlertStubComponent, 0, 0);
+ });
+
+ it('... should not contain a loading spinner component (stubbed)', () => {
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+
+ getAndExpectDebugElementByDirective(divDes[0], TwelveToneSpinnerStubComponent, 0, 0);
+ });
+
+ it('... should not contain an AccoladeComponent (stubbed)', () => {
+ getAndExpectDebugElementByDirective(compDe, EditionAccoladeStubComponent, 0, 0);
+ });
+
+ it('... should not contain a ConvoluteComponent (stubbed)', () => {
+ getAndExpectDebugElementByDirective(compDe, EditionConvoluteStubComponent, 0, 0);
+ });
+ });
});
describe('AFTER initial data binding', () => {
@@ -289,6 +363,64 @@ describe('EditionSheetsComponent', () => {
expectToEqual(mockActivatedRoute.snapshot.url[0].path, changedPath);
});
+ describe('VIEW', () => {
+ it('... should contain one div.awg-sheets-view', () => {
+ getAndExpectDebugElementByCss(compDe, 'div.awg-sheets-view', 1, 1);
+ });
+
+ it('... should contain one AccoladeComponent (stubbed)', () => {
+ getAndExpectDebugElementByDirective(compDe, EditionAccoladeStubComponent, 1, 1);
+ });
+
+ it('... should contain no ConvoluteComponent (stubbed) if no convolute is provided', () => {
+ getAndExpectDebugElementByDirective(compDe, EditionConvoluteStubComponent, 0, 0);
+ });
+
+ describe('on error', () => {
+ const expectedError = { status: 404, statusText: 'got Error' };
+
+ beforeEach(waitForAsync(() => {
+ // Spy on editionDataService to return an error
+ editionDataServiceGetEditionSheetsDataSpy.and.returnValue(
+ observableThrowError(() => expectedError)
+ );
+
+ component.getEditionSheetsData();
+ detectChangesOnPush(fixture);
+ }));
+
+ it('... should not contain sheets view, but one ErrorAlertComponent (stubbed)', waitForAsync(() => {
+ getAndExpectDebugElementByCss(compDe, 'div.awg-sheets-view', 0, 0);
+
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div', 1, 1);
+ getAndExpectDebugElementByDirective(divDes[0], ErrorAlertStubComponent, 1, 1);
+ }));
+
+ it('... should pass down error object to ErrorAlertComponent', waitForAsync(() => {
+ const errorAlertDes = getAndExpectDebugElementByDirective(compDe, ErrorAlertStubComponent, 1, 1);
+ const errorAlertCmp = errorAlertDes[0].injector.get(
+ ErrorAlertStubComponent
+ ) as ErrorAlertStubComponent;
+
+ expectToEqual(errorAlertCmp.errorObject, expectedError);
+ }));
+ });
+
+ describe('on loading', () => {
+ describe('... should contain only TwelveToneSpinnerComponent (stubbed) if ... ', () => {
+ it('... isLoading is true', () => {
+ component.isLoading = true;
+ detectChangesOnPush(fixture);
+
+ getAndExpectDebugElementByCss(compDe, 'div.awg-sheets-view', 0, 0);
+ getAndExpectDebugElementByDirective(compDe, ErrorAlertStubComponent, 0, 0);
+
+ getAndExpectDebugElementByDirective(compDe, TwelveToneSpinnerStubComponent, 1, 1);
+ });
+ });
+ });
+ });
+
describe('#onReportFragmentNavigate()', () => {
it('... should have a method `onReportFragmentNavigate`', () => {
expect(component.onReportFragmentNavigate).toBeDefined();
@@ -523,6 +655,232 @@ describe('EditionSheetsComponent', () => {
});
});
+ describe('#_assignData()', () => {
+ it('... should have a method `_assignData`', () => {
+ expect((component as any)._assignData).toBeDefined();
+ });
+
+ it('... should assign data from the service to the component', () => {
+ component.folioConvoluteData = undefined;
+ component.svgSheetsData = undefined;
+ component.textcriticsData = undefined;
+ detectChangesOnPush(fixture);
+
+ const expectedData = [expectedFolioConvoluteData, expectedSvgSheetsData, expectedTextcriticsData];
+
+ (component as any)._assignData(expectedData);
+
+ expectToEqual(component.folioConvoluteData, expectedFolioConvoluteData);
+ expectToEqual(component.svgSheetsData, expectedSvgSheetsData);
+ expectToEqual(component.textcriticsData, expectedTextcriticsData);
+ });
+ });
+
+ describe('#_getDefaultSheetId()', () => {
+ it('... should have a method `_getDefaultSheetId`', () => {
+ expect((component as any)._getDefaultSheetId).toBeDefined();
+ });
+
+ describe('... should return an empty string if', () => {
+ it('... should return an empty string if svgSheetsData is undefined', () => {
+ component.svgSheetsData = undefined;
+ detectChangesOnPush(fixture);
+
+ const result = (component as any)._getDefaultSheetId();
+
+ expectToBe(result, '');
+ });
+
+ it('... should return an empty string if svgSheetsData.sheets.sketchEditions is an empty array', () => {
+ component.svgSheetsData = { sheets: { sketchEditions: [] } } as EditionSvgSheetList;
+ detectChangesOnPush(fixture);
+
+ const result = (component as any)._getDefaultSheetId();
+
+ expectToBe(result, '');
+ });
+ });
+
+ it('... should return the id of the first sketch sheet by default (no partials)', () => {
+ const mockSheet1 = { id: 'sheet1', content: [] } as EditionSvgSheet;
+
+ component.svgSheetsData = {
+ sheets: { sketchEditions: [mockSheet1] },
+ } as EditionSvgSheetList;
+ detectChangesOnPush(fixture);
+
+ const result = (component as any)._getDefaultSheetId();
+
+ expectToBe(result, mockSheet1.id);
+ });
+
+ it('... should return the id and first partial of the first sketch sheet by default if partials are present', () => {
+ const mockSheet1 = {
+ id: 'sheet1',
+ content: [
+ { svg: '', image: '', partial: 'a' },
+ { svg: '', image: '', partial: 'b' },
+ ],
+ } as EditionSvgSheet;
+ component.svgSheetsData = {
+ sheets: { sketchEditions: [mockSheet1] },
+ } as EditionSvgSheetList;
+ detectChangesOnPush(fixture);
+
+ const result = (component as any)._getDefaultSheetId();
+
+ expectToBe(result, 'sheet1a');
+ });
+
+ it('... should return the first id and partial of the first sketch sheet from a list of multiple sheets', () => {
+ const mockSheet1 = {
+ id: 'sheet1',
+ content: [
+ { svg: '', image: '', partial: 'a' },
+ { svg: '', image: '', partial: 'b' },
+ ],
+ } as EditionSvgSheet;
+ const mockSheet2 = {
+ id: 'sheet2',
+ content: [
+ { svg: '', image: '', partial: 'c' },
+ { svg: '', image: '', partial: 'd' },
+ ],
+ } as EditionSvgSheet;
+ component.svgSheetsData = {
+ sheets: { sketchEditions: [mockSheet1, mockSheet2] },
+ } as EditionSvgSheetList;
+
+ const result = (component as any)._getDefaultSheetId();
+
+ expectToBe(result, 'sheet1a');
+ });
+
+ it('... should return the first id and partial of the first sketch sheet from a list of multiple edition types', () => {
+ const mockSheet1 = {
+ id: 'sheet1',
+ content: [
+ { svg: '', image: '', partial: 'a' },
+ { svg: '', image: '', partial: 'b' },
+ ],
+ } as EditionSvgSheet;
+ const mockSheet2 = { id: 'sheet2', content: [] } as EditionSvgSheet;
+ const mockSheet3 = {
+ id: 'sheet3',
+ content: [
+ { svg: '', image: '', partial: 'c' },
+ { svg: '', image: '', partial: 'd' },
+ ],
+ } as EditionSvgSheet;
+ component.svgSheetsData = {
+ sheets: {
+ workEditions: [mockSheet1],
+ textEditions: [mockSheet2],
+ sketchEditions: [mockSheet3],
+ },
+ } as EditionSvgSheetList;
+
+ const result = (component as any)._getDefaultSheetId();
+
+ expectToBe(result, 'sheet3c');
+ });
+ });
+
+ describe('#_handleQueryParams()', () => {
+ it('... should have a method `_handleQueryParams`', () => {
+ expect((component as any)._handleQueryParams).toBeDefined();
+ });
+
+ describe('... with svgSheetsData available and id given from query params', () => {
+ it('... should trigger `_selectSvgSheet` with the correct sheet id', () => {
+ const sheetId = 'test-TF1';
+ mockActivatedRoute.testQueryParamMap = { id: sheetId };
+ detectChangesOnPush(fixture);
+
+ (component as any)._handleQueryParams(mockActivatedRoute.testQueryParamMap);
+
+ expectSpyCall(selectSvgSheetSpy, 2, sheetId);
+ });
+ });
+
+ describe('... with svgSheetsData available and id not given from query params', () => {
+ it('... should trigger `onSvgSheetSelect` with snapshotQueryParamsId on first page load', () => {
+ mockActivatedRoute.testQueryParamMap = { id: '' };
+ (component as any)._isFirstPageLoad = true;
+
+ const snapShotSheetId = 'test-TF1';
+ component.snapshotQueryParamsId = snapShotSheetId;
+ detectChangesOnPush(fixture);
+
+ (component as any)._handleQueryParams(mockActivatedRoute.testQueryParamMap);
+
+ expectSpyCall(onSvgSheetSelectSpy, 3, {
+ complexId: '',
+ sheetId: snapShotSheetId,
+ });
+ });
+
+ it('... should trigger `onSvgSheetSelect` with default id on subsequent page loads', () => {
+ mockActivatedRoute.testQueryParamMap = { id: '' };
+ (component as any)._isFirstPageLoad = false;
+
+ const defaultSheetId = 'test-1';
+ const snapShotSheetId = 'test-TF1';
+ component.snapshotQueryParamsId = snapShotSheetId;
+ detectChangesOnPush(fixture);
+
+ (component as any)._handleQueryParams(mockActivatedRoute.testQueryParamMap);
+
+ expectSpyCall(onSvgSheetSelectSpy, 3, {
+ complexId: '',
+ sheetId: defaultSheetId,
+ });
+ });
+ });
+
+ describe('... with svgSheetsData not available and id not given from query params', () => {
+ it('... should trigger `onSvgSheetSelect` with no id', () => {
+ mockActivatedRoute.testQueryParamMap = { id: '' };
+ (component as any)._isFirstPageLoad = true;
+
+ component.svgSheetsData = undefined;
+ component.snapshotQueryParamsId = '';
+ detectChangesOnPush(fixture);
+
+ (component as any)._handleQueryParams(mockActivatedRoute.testQueryParamMap);
+
+ expectSpyCall(onSvgSheetSelectSpy, 3, {
+ complexId: '',
+ sheetId: '',
+ });
+ });
+ it('... should reset selectedSvgSheet to undefined', () => {
+ mockActivatedRoute.testQueryParamMap = { id: '' };
+ (component as any)._isFirstPageLoad = true;
+
+ component.svgSheetsData = undefined;
+ component.snapshotQueryParamsId = '';
+ detectChangesOnPush(fixture);
+
+ (component as any)._handleQueryParams(mockActivatedRoute.testQueryParamMap);
+
+ expect(component.selectedSvgSheet).toBeUndefined();
+ });
+ });
+
+ it('... should set _isFirstPageLoad and isLoading to false after handling query params', () => {
+ component.isLoading = true;
+ (component as any)._isFirstPageLoad = true;
+ mockActivatedRoute.testQueryParamMap = { id: 'sheetId' };
+ detectChangesOnPush(fixture);
+
+ (component as any)._handleQueryParams(mockActivatedRoute.testQueryParamMap);
+
+ expectToBe((component as any)._isFirstPageLoad, false);
+ expectToBe(component.isLoading, false);
+ });
+ });
+
describe('#_navigateWithComplexId()', () => {
it('... should have a method `_navigateWithComplexId`', () => {
expect((component as any)._navigateWithComplexId).toBeDefined();
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.ts
index e4057d299..8d12768c0 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-sheets.component.ts
@@ -1,8 +1,8 @@
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, NavigationExtras, ParamMap, Router } from '@angular/router';
-import { Observable, Subject, combineLatest } from 'rxjs';
-import { switchMap, takeUntil, tap } from 'rxjs/operators';
+import { EMPTY, Observable, Subject, combineLatest } from 'rxjs';
+import { catchError, switchMap, takeUntil, tap } from 'rxjs/operators';
import { UtilityService } from '@awg-core/services';
import { ModalComponent } from '@awg-shared/modal/modal.component';
@@ -14,7 +14,7 @@ import {
EditionSvgSheetList,
FolioConvolute,
FolioConvoluteList,
- TextcriticalComment,
+ TextcriticalCommentBlock,
Textcritics,
TextcriticsList,
} from '@awg-views/edition-view/models';
@@ -50,11 +50,18 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
editionComplex: EditionComplex;
/**
- * Public variable: errorMessage.
+ * Public variable: errorObject.
*
- * It keeps an errorMessage for the service calls.
+ * It keeps an errorObject for the service calls.
*/
- errorMessage: string = undefined;
+ errorObject = null;
+
+ /**
+ * Public variable: isLoading.
+ *
+ * It keeps the loading status of the edition sheets.
+ */
+ isLoading = true;
/**
* Public variable: folioConvoluteData.
@@ -78,11 +85,11 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
selectedSvgSheet: EditionSvgSheet;
/**
- * Public variable: selectedTextcriticalComments.
+ * Public variable: selectedTextcriticalCommentBlocks.
*
- * It keeps the selected textcritical comments.
+ * It keeps the selected textcritical comment blocks.
*/
- selectedTextcriticalComments: TextcriticalComment[];
+ selectedTextcriticalCommentBlocks: TextcriticalCommentBlock[];
/**
* Public variable: selectedTextcritics.
@@ -183,18 +190,28 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
* @returns {void} Gets the current edition complex and all necessary edition data.
*/
getEditionSheetsData(): void {
+ this.errorObject = null;
+
this.snapshotQueryParamsId = this.route.snapshot.queryParamMap.get('id');
combineLatest([this.route.paramMap, this.route.queryParamMap])
.pipe(
switchMap(([_params, queryParams]) => this._fetchEditionComplexData(queryParams)),
+ // Error handling
+ catchError(err => {
+ this.errorObject = err;
+ this.isLoading = false;
+ return EMPTY;
+ }),
takeUntil(this._destroyed$)
)
.subscribe({
- next: () => {},
+ next: () => {
+ this.isLoading = false;
+ },
error: err => {
- console.error(err);
- this.errorMessage = err;
+ this.errorObject = err;
+ this.isLoading = false;
},
});
}
@@ -247,12 +264,12 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
* @returns {void} Sets the selectedTextcriticalComments and showTka variable.
*/
onOverlaySelect(overlays: EditionSvgOverlay[]): void {
- this.selectedTextcriticalComments = this.editionSheetsService.getTextcriticalCommentsForOverlays(
+ this.selectedTextcriticalCommentBlocks = this.editionSheetsService.getTextcriticalCommentsForOverlays(
this.selectedTextcritics.comments,
overlays
);
- this.showTkA = this.utils.isNotEmptyArray(this.selectedTextcriticalComments);
+ this.showTkA = this.utils.isNotEmptyArray(this.selectedTextcriticalCommentBlocks);
}
/**
@@ -343,7 +360,8 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
private _fetchEditionComplexData(
queryParams: ParamMap
): Observable {
- return this.editionService.getEditionComplex().pipe(
+ this.isLoading = true;
+ return this.editionService.getSelectedEditionComplex().pipe(
// Set editionComplex
tap((complex: EditionComplex) => (this.editionComplex = complex)),
// Get editionSheetsData
@@ -388,6 +406,12 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
? this.snapshotQueryParamsId
: this._getDefaultSheetId();
+ // Reset selectedSvgSheet if no sheetId is provided
+ if (sheetIdFromQueryParams === '') {
+ this.selectedSvgSheet = undefined;
+ }
+
+ // Navigate once more to the selected sheet
this.onSvgSheetSelect({
complexId: '',
sheetId: sheetIdFromQueryParams,
@@ -395,6 +419,7 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
}
this._isFirstPageLoad = false;
+ this.isLoading = false;
}
/**
@@ -444,7 +469,7 @@ export class EditionSheetsComponent implements OnInit, OnDestroy {
this.utils.isNotEmptyObject(this.selectedTextcritics) &&
this.utils.isNotEmptyArray(this.selectedTextcritics.comments)
) {
- this.selectedTextcriticalComments = this.selectedTextcritics.comments;
+ this.selectedTextcriticalCommentBlocks = this.selectedTextcritics.comments;
}
}
}
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-description/edition-tka-description.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-description/edition-tka-description.component.spec.ts
index 41f3c24a2..06a6483d4 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-description/edition-tka-description.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-description/edition-tka-description.component.spec.ts
@@ -12,7 +12,7 @@ import {
} from '@testing/expect-helper';
import { mockEditionData } from '@testing/mock-data';
-import { CompileHtmlComponent } from '@awg-app/shared/compile-html';
+import { CompileHtmlComponent } from '@awg-shared/compile-html';
import { EditionSvgSheet } from '@awg-views/edition-view/models';
import { DOCUMENT } from '@angular/common';
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.html
index 99a3f9a9b..b1d6a69a5 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.html
@@ -8,15 +8,24 @@
}
- @if (textcriticalComments) {
+ @if (textcriticalCommentBlocks) {
- @for (textcriticalComment of textcriticalComments; track $index) {
-
- |
- |
- |
- |
-
+ @for (textcriticalCommentBlock of textcriticalCommentBlocks; track $index) {
+ @if (textcriticalCommentBlock.blockHeader) {
+
+
+
+ }
+ @for (textcriticalComment of textcriticalCommentBlock.blockComments; track $index) {
+
+ |
+ |
+ |
+ |
+
+ }
}
}
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.spec.ts
index c93c56283..f777ee1e9 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.spec.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.spec.ts
@@ -8,6 +8,7 @@ import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
import {
expectSpyCall,
expectToBe,
+ expectToContain,
expectToEqual,
getAndExpectDebugElementByCss,
getAndExpectDebugElementByDirective,
@@ -16,7 +17,7 @@ import { mockEditionData } from '@testing/mock-data';
import { CompileHtmlComponent } from '@awg-shared/compile-html';
import { EDITION_GLYPHS_DATA } from '@awg-views/edition-view/data';
-import { EditionSvgSheet, TextcriticalComment, TkaTableHeaderColumn } from '@awg-views/edition-view/models';
+import { EditionSvgSheet, TextcriticalCommentBlock, TkaTableHeaderColumn } from '@awg-views/edition-view/models';
import { EditionTkaTableComponent } from './edition-tka-table.component';
@@ -44,8 +45,9 @@ describe('EditionTkaTableComponent (DONE)', () => {
let expectedNextComplexId: string;
let expectedSvgSheet: EditionSvgSheet;
let expectedNextSvgSheet: EditionSvgSheet;
- let expectedTextcriticalComments: TextcriticalComment[];
+ let expectedTextcriticalCommentBlocks: TextcriticalCommentBlock[];
let expectedTableHeaderStrings: { [key: string]: TkaTableHeaderColumn[] };
+ let expectedTotalRows: number;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
@@ -68,7 +70,14 @@ describe('EditionTkaTableComponent (DONE)', () => {
expectedModalSnippet = JSON.parse(JSON.stringify(mockEditionData.mockModalSnippet));
expectedSvgSheet = JSON.parse(JSON.stringify(mockEditionData.mockSvgSheet_Sk1));
expectedNextSvgSheet = JSON.parse(JSON.stringify(mockEditionData.mockSvgSheet_Sk2));
- expectedTextcriticalComments = mockEditionData.mockTextcriticsData.textcritics.at(1).comments;
+ expectedTextcriticalCommentBlocks = mockEditionData.mockTextcriticsData.textcritics.at(1).comments;
+
+ const totalBlockHeaders = expectedTextcriticalCommentBlocks.filter(block => block.blockHeader).length;
+ const totalBlockComments = expectedTextcriticalCommentBlocks.reduce(
+ (acc, block) => acc + block.blockComments.length,
+ 0
+ );
+ expectedTotalRows = totalBlockHeaders + totalBlockComments;
expectedIsRowTable = false;
expectedTableHeaderStrings = {
@@ -113,8 +122,8 @@ describe('EditionTkaTableComponent (DONE)', () => {
});
describe('BEFORE initial data binding', () => {
- it('... should not have textcriticalComments', () => {
- expect(component.textcriticalComments).toBeUndefined();
+ it('... should not have textcriticalCommentBlocks', () => {
+ expect(component.textcriticalCommentBlocks).toBeUndefined();
});
it('... should have isRowTable = false', () => {
@@ -151,152 +160,200 @@ describe('EditionTkaTableComponent (DONE)', () => {
describe('AFTER initial data binding', () => {
beforeEach(() => {
// Simulate the parent setting the input properties
- component.textcriticalComments = expectedTextcriticalComments;
+ component.textcriticalCommentBlocks = expectedTextcriticalCommentBlocks;
component.isRowTable = expectedIsRowTable;
// Trigger initial data binding
fixture.detectChanges();
});
- it('... should have textcriticalComments', () => {
- expectToBe(component.textcriticalComments, expectedTextcriticalComments);
+ it('... should have textcriticalCommentBlocks', () => {
+ expectToBe(component.textcriticalCommentBlocks, expectedTextcriticalCommentBlocks);
});
describe('VIEW', () => {
- it('... should contain one row (tr) with four columns (th) in table head', () => {
- const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
- getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
- });
+ describe('... table header', () => {
+ it('... should contain one row (tr) with four columns (th) in table head', () => {
+ const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
+ getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
+ });
- it('... should display rowTable table header if `isRowTable` flag is given', () => {
- component.isRowTable = true;
- detectChangesOnPush(fixture);
+ it('... should display rowTable table header if `isRowTable` flag is given', () => {
+ component.isRowTable = true;
+ detectChangesOnPush(fixture);
- const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
- const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
+ const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
+ const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
- columnDes.forEach((columnDe, index) => {
- const columnEl = columnDe.nativeElement;
- expectToBe(columnEl.textContent.trim(), expectedTableHeaderStrings['rowTable'][index].label);
+ columnDes.forEach((columnDe, index) => {
+ const columnEl = columnDe.nativeElement;
+ expectToBe(columnEl.textContent.trim(), expectedTableHeaderStrings['rowTable'][index].label);
+ });
});
- });
- it('... should display corrections table header if `isCorrections` flag is given', () => {
- component.isCorrections = true;
- detectChangesOnPush(fixture);
+ it('... should display corrections table header if `isCorrections` flag is given', () => {
+ component.isCorrections = true;
+ detectChangesOnPush(fixture);
- const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
- const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
+ const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
+ const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
- columnDes.forEach((columnDe, index) => {
- const columnEl = columnDe.nativeElement;
- expectToBe(columnEl.textContent.trim(), expectedTableHeaderStrings['corrections'][index].label);
+ columnDes.forEach((columnDe, index) => {
+ const columnEl = columnDe.nativeElement;
+ expectToBe(columnEl.textContent.trim(), expectedTableHeaderStrings['corrections'][index].label);
+ });
});
- });
- it('... should display default table header if `isRowTable` or `isCorrections` flags are not given', () => {
- const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
- const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
+ it('... should display default table header if `isRowTable` or `isCorrections` flags are not given', () => {
+ const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
+ const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
- columnDes.forEach((columnDe, index) => {
- const columnEl = columnDe.nativeElement;
- expectToBe(columnEl.textContent.trim(), expectedTableHeaderStrings['default'][index].label);
+ columnDes.forEach((columnDe, index) => {
+ const columnEl = columnDe.nativeElement;
+ expectToBe(columnEl.textContent.trim(), expectedTableHeaderStrings['default'][index].label);
+ });
});
- });
- it('... should display default table header with adjusted comment colum if `isSketchId` flag is true', () => {
- component.isSketchId = true;
- detectChangesOnPush(fixture);
+ it('... should display default table header with adjusted comment colum if `isSketchId` flag is true', () => {
+ component.isSketchId = true;
+ detectChangesOnPush(fixture);
- const expected = expectedTableHeaderStrings['default'];
- expected[3].label = 'Kommentar';
+ const expected = expectedTableHeaderStrings['default'];
+ expected[3].label = 'Kommentar';
- const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
- const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
+ const tableHeadDes = getAndExpectDebugElementByCss(compDe, 'table > thead > tr', 1, 1);
+ const columnDes = getAndExpectDebugElementByCss(tableHeadDes[0], 'th', 4, 4);
- columnDes.forEach((columnDe, index) => {
- const columnEl = columnDe.nativeElement;
- expectToBe(columnEl.textContent.trim(), expected[index].label);
+ columnDes.forEach((columnDe, index) => {
+ const columnEl = columnDe.nativeElement;
+ expectToBe(columnEl.textContent.trim(), expected[index].label);
+ });
});
});
- it('... should contain one table body', () => {
- const tableDes = getAndExpectDebugElementByCss(compDe, 'table', 1, 1);
+ describe('... table body', () => {
+ it('... should contain no table body if textcritical comment blocks are not provided', () => {
+ component.textcriticalCommentBlocks = undefined;
+ detectChangesOnPush(fixture);
- getAndExpectDebugElementByCss(tableDes[0], 'thead', 1, 1);
- getAndExpectDebugElementByCss(tableDes[0], 'tbody', 1, 1);
- });
+ const tableDes = getAndExpectDebugElementByCss(compDe, 'table', 1, 1);
- it('... should contain as many rows (tr) in table body as entries in textcritical comments', () => {
- getAndExpectDebugElementByCss(
- compDe,
- 'table > tbody > tr',
- expectedTextcriticalComments.length,
- expectedTextcriticalComments.length
- );
- });
+ getAndExpectDebugElementByCss(tableDes[0], 'thead', 1, 1);
+ getAndExpectDebugElementByCss(tableDes[0], 'tbody', 0, 0);
+ });
- it('... should contain four cells (td) in each row (tr) in table body', () => {
- const rows = getAndExpectDebugElementByCss(
- compDe,
- 'table > tbody > tr',
- expectedTextcriticalComments.length,
- expectedTextcriticalComments.length
- );
+ it('... should contain one table body if textcritical comment blocks are provided ', () => {
+ const tableDes = getAndExpectDebugElementByCss(compDe, 'table', 1, 1);
- rows.forEach(row => {
- getAndExpectDebugElementByCss(row, 'td', 4, 4);
+ getAndExpectDebugElementByCss(tableDes[0], 'thead', 1, 1);
+ getAndExpectDebugElementByCss(tableDes[0], 'tbody', 1, 1);
});
- });
- it('... should contain correct data in all row cells (tr/td)', () => {
- const rows = getAndExpectDebugElementByCss(
- compDe,
- 'table > tbody > tr',
- expectedTextcriticalComments.length,
- expectedTextcriticalComments.length
- );
- rows.forEach((row, index) => {
- const rowCells = getAndExpectDebugElementByCss(row, 'td', 4, 4);
-
- const measureCell = rowCells[0].nativeElement;
- const systemCell = rowCells[1].nativeElement;
- const positionCell = rowCells[2].nativeElement;
- const commentCell = rowCells[3].nativeElement;
-
- const measureCellHtmlSnippet = mockDocument.createElement('span');
- measureCellHtmlSnippet.innerHTML = expectedTextcriticalComments[index].measure;
- if (index === 2) {
- measureCellHtmlSnippet.innerHTML = '{13}';
- }
-
- const commentCellHtmlSnippet = mockDocument.createElement('span');
- commentCellHtmlSnippet.innerHTML = expectedTextcriticalComments[index].comment;
- if (index === 2) {
- commentCellHtmlSnippet.innerHTML = '♮ überschreibt ♭.';
- }
-
- expectToBe(measureCell.textContent, measureCellHtmlSnippet.textContent);
- expectToBe(systemCell.textContent, expectedTextcriticalComments[index].system);
- expectToBe(positionCell.textContent, expectedTextcriticalComments[index].position);
- expectToBe(commentCell.textContent, commentCellHtmlSnippet.textContent);
+ it('... should contain rows (tr) for each textcritical comment and block header in table body', () => {
+ getAndExpectDebugElementByCss(compDe, 'table > tbody > tr', expectedTotalRows, expectedTotalRows);
});
- });
- it('... should contain CompileHtmlComponent only in fourth cell (td) of each row (tr)', () => {
- const rows = getAndExpectDebugElementByCss(
- compDe,
- 'table > tbody > tr',
- expectedTextcriticalComments.length,
- expectedTextcriticalComments.length
- );
- rows.forEach(row => {
- const rowCells = getAndExpectDebugElementByCss(row, 'td', 4, 4);
+ it('... should contain one cell (td colspan=4) for block headers and four cells (td) for block comments in each row (tr) in table body', () => {
+ const rows = getAndExpectDebugElementByCss(
+ compDe,
+ 'table > tbody > tr',
+ expectedTotalRows,
+ expectedTotalRows
+ );
+
+ let rowIndex = 0;
+ expectedTextcriticalCommentBlocks.forEach(block => {
+ if (block.blockHeader) {
+ const tdDes = getAndExpectDebugElementByCss(rows[rowIndex], 'td', 1, 1);
+ const tdEl = tdDes[0].nativeElement;
+ expectToBe(tdEl.getAttribute('colspan'), '4');
+ expectToContain(tdEl.classList, 'awg-edition-tka-table-block-header');
+
+ rowIndex++;
+ }
+ block.blockComments.forEach(() => {
+ getAndExpectDebugElementByCss(rows[rowIndex], 'td', 4, 4);
+
+ rowIndex++;
+ });
+ });
+ });
+
+ it('... should contain correct data in all row cells (tr/td)', () => {
+ const rows = getAndExpectDebugElementByCss(
+ compDe,
+ 'table > tbody > tr',
+ expectedTotalRows,
+ expectedTotalRows
+ );
+
+ let rowIndex = 0;
+ expectedTextcriticalCommentBlocks.forEach(block => {
+ if (block.blockHeader) {
+ const tdDes = getAndExpectDebugElementByCss(
+ rows[rowIndex],
+ 'td.awg-edition-tka-table-block-header',
+ 1,
+ 1
+ );
+ const tdEl = tdDes[0].nativeElement;
+
+ expectToBe(tdEl.textContent, block.blockHeader);
+
+ rowIndex++;
+ }
+ block.blockComments.forEach((comment, index) => {
+ const rowCells = getAndExpectDebugElementByCss(rows[rowIndex], 'td', 4, 4);
+
+ const measureCell = rowCells[0].nativeElement;
+ const systemCell = rowCells[1].nativeElement;
+ const positionCell = rowCells[2].nativeElement;
+ const commentCell = rowCells[3].nativeElement;
+
+ const measureCellHtmlSnippet = mockDocument.createElement('span');
+ measureCellHtmlSnippet.innerHTML = index === 2 ? '{13}' : comment.measure;
+
+ const commentCellHtmlSnippet = mockDocument.createElement('span');
+ commentCellHtmlSnippet.innerHTML = index === 2 ? '♮ überschreibt ♭.' : comment.comment;
+
+ expectToBe(measureCell.textContent, measureCellHtmlSnippet.textContent);
+ expectToBe(systemCell.textContent, comment.system);
+ expectToBe(positionCell.textContent, comment.position);
+ expectToBe(commentCell.textContent, commentCellHtmlSnippet.textContent);
+
+ rowIndex++;
+ });
+ });
+ });
- getAndExpectDebugElementByDirective(rowCells[0], CompileHtmlComponent, 0, 0);
- getAndExpectDebugElementByDirective(rowCells[1], CompileHtmlComponent, 0, 0);
- getAndExpectDebugElementByDirective(rowCells[2], CompileHtmlComponent, 0, 0);
- getAndExpectDebugElementByDirective(rowCells[3], CompileHtmlComponent, 1, 1);
+ it('... should contain CompileHtmlComponent in each header cell or fourth cell (td) of a block comment', () => {
+ const rows = getAndExpectDebugElementByCss(
+ compDe,
+ 'table > tbody > tr',
+ expectedTotalRows,
+ expectedTotalRows
+ );
+
+ let rowIndex = 0;
+ expectedTextcriticalCommentBlocks.forEach(block => {
+ if (block.blockHeader) {
+ const tdDes = getAndExpectDebugElementByCss(rows[rowIndex], 'td', 1, 1);
+
+ getAndExpectDebugElementByDirective(tdDes[0], CompileHtmlComponent, 1, 1);
+
+ rowIndex++;
+ }
+ block.blockComments.forEach(() => {
+ const tdDes = getAndExpectDebugElementByCss(rows[rowIndex], 'td', 4, 4);
+
+ getAndExpectDebugElementByDirective(tdDes[0], CompileHtmlComponent, 0, 0);
+ getAndExpectDebugElementByDirective(tdDes[1], CompileHtmlComponent, 0, 0);
+ getAndExpectDebugElementByDirective(tdDes[2], CompileHtmlComponent, 0, 0);
+ getAndExpectDebugElementByDirective(tdDes[3], CompileHtmlComponent, 1, 1);
+
+ rowIndex++;
+ });
+ });
});
});
});
@@ -322,12 +379,13 @@ describe('EditionTkaTableComponent (DONE)', () => {
expectToBe(component.getGlyph('[#]'), '\u266F'); // SHARP
expectToBe(component.getGlyph('[a]'), '\u266E'); // NATURAL
expectToBe(component.getGlyph('[f]'), '\uD834\uDD91'); // FORTE
+ expectToBe(component.getGlyph('[ped]'), '\uD834\uDDAE'); // PEDAL
});
it('... should return an empty string for an invalid glyph alt value', () => {
- expect(component.getGlyph('')).toBe('');
- expect(component.getGlyph('[invalid]')).toBe('');
- expect(component.getGlyph('[not found]')).toBe('');
+ expectToBe(component.getGlyph(''), '');
+ expectToBe(component.getGlyph('[invalid]'), '');
+ expectToBe(component.getGlyph('[not found]'), '');
});
});
@@ -428,14 +486,14 @@ describe('EditionTkaTableComponent (DONE)', () => {
const rows = getAndExpectDebugElementByCss(
compDe,
'table > tbody > tr',
- expectedTextcriticalComments.length,
- expectedTextcriticalComments.length
+ expectedTotalRows,
+ expectedTotalRows
);
- // Find spans of second row
- const spanDes = getAndExpectDebugElementByCss(rows[1], 'td > span', 1, 1);
+ // Find spans of third row
+ const spanDes = getAndExpectDebugElementByCss(rows[2], 'td > span', 1, 1);
- // Find anchors in second span
+ // Find anchors in span
const anchorDes = getAndExpectDebugElementByCss(spanDes[0], 'a', 3, 3);
// Trigger click with click helper & wait for changes
@@ -509,14 +567,14 @@ describe('EditionTkaTableComponent (DONE)', () => {
const rows = getAndExpectDebugElementByCss(
compDe,
'table > tbody > tr',
- expectedTextcriticalComments.length,
- expectedTextcriticalComments.length
+ expectedTotalRows,
+ expectedTotalRows
);
- // Find spans of second row
- const spanDes = getAndExpectDebugElementByCss(rows[1], 'td > span', 1, 1);
+ // Find spans of third row
+ const spanDes = getAndExpectDebugElementByCss(rows[2], 'td > span', 1, 1);
- // Find anchors in second span
+ // Find anchors in span
const anchorDes = getAndExpectDebugElementByCss(spanDes[0], 'a', 3, 3);
// Click on first anchor with modal call
@@ -547,14 +605,14 @@ describe('EditionTkaTableComponent (DONE)', () => {
const rows = getAndExpectDebugElementByCss(
compDe,
'table > tbody > tr',
- expectedTextcriticalComments.length,
- expectedTextcriticalComments.length
+ expectedTotalRows,
+ expectedTotalRows
);
- // Find spans of second row
- const spanDes = getAndExpectDebugElementByCss(rows[1], 'td > span', 1, 1);
+ // Find spans of third row
+ const spanDes = getAndExpectDebugElementByCss(rows[2], 'td > span', 1, 1);
- // Find anchors in second span
+ // Find anchors in span
const anchorDes = getAndExpectDebugElementByCss(spanDes[0], 'a', 3, 3);
// Trigger click with click helper & wait for changes
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.ts
index e974724ee..db4d92896 100644
--- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.ts
+++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-tka/edition-tka-table/edition-tka-table.component.ts
@@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
-import { EDITION_GLYPHS_DATA } from '@awg-app/views/edition-view/data';
-import { TextcriticalComment, TkaTableHeaderColumn } from '@awg-views/edition-view/models';
+import { EDITION_GLYPHS_DATA } from '@awg-views/edition-view/data';
+import { TextcriticalCommentBlock, TkaTableHeaderColumn } from '@awg-views/edition-view/models';
/**
* The EditionTkaTable component.
@@ -17,12 +17,12 @@ import { TextcriticalComment, TkaTableHeaderColumn } from '@awg-views/edition-vi
})
export class EditionTkaTableComponent {
/**
- * Input variable: textcriticalComments.
+ * Input variable: textcriticalCommentBlocks.
*
- * It keeps the textcritical comments.
+ * It keeps the textcritical comment blocks.
*/
@Input()
- textcriticalComments: TextcriticalComment[];
+ textcriticalCommentBlocks: TextcriticalCommentBlock[];
/**
* Input variable: isCorrections.
diff --git a/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface-routing.module.ts b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface-routing.module.ts
new file mode 100644
index 000000000..cf58b80d7
--- /dev/null
+++ b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface-routing.module.ts
@@ -0,0 +1,30 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { EditionPrefaceComponent } from './edition-preface.component';
+
+/* Routes of the EditionPrefaceModule */
+const EDITION_PREFACE_ROUTES: Routes = [
+ {
+ path: '',
+ component: EditionPrefaceComponent,
+ data: { title: 'AWG Online Edition – Preface' },
+ },
+];
+
+/**
+ * Routed components of the {@link EditionPrefaceModule}:
+ * {@link EditionPrefaceComponent}.
+ */
+export const routedEditionPrefaceComponents = [EditionPrefaceComponent];
+
+/**
+ * EditionPreface module routing.
+ *
+ * It activates the EDITION_PREFACE_ROUTES.
+ */
+@NgModule({
+ imports: [RouterModule.forChild(EDITION_PREFACE_ROUTES)],
+ exports: [RouterModule],
+})
+export class EditionPrefaceRoutingModule {}
diff --git a/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.html b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.html
new file mode 100644
index 000000000..b3f868dec
--- /dev/null
+++ b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.html
@@ -0,0 +1,12 @@
+@if (prefaceData$ | async; as prefaceData) {
+
+
+ DE
+ |
+ EN
+
+ @for (prefaceParagraph of prefaceData.preface[currentLanguage].content; track $index) {
+
+ }
+
+}
diff --git a/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.scss b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.scss
new file mode 100644
index 000000000..6e7b96721
--- /dev/null
+++ b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.scss
@@ -0,0 +1,56 @@
+@import '/src/assets/themes/scss/shared';
+
+.awg-language-switcher {
+ font-family: 'Montserrat', sans-serif;
+ font-size: small;
+ text-align: end;
+
+ a {
+ cursor: pointer;
+ text-decoration: none;
+ color: inherit;
+ // disable the active link style
+ &.active,
+ &.active:hover {
+ cursor: default;
+ color: inherit;
+ }
+ &:not(.active) {
+ color: $link-color;
+ }
+ &:hover {
+ border-bottom: none !important;
+ }
+ }
+}
+
+.awg-preface-para {
+ margin: 0;
+ text-indent: 25px;
+
+ &::ng-deep {
+ .heading {
+ display: block;
+ margin-bottom: 25px;
+ font-size: 1.5em;
+ font-weight: bold;
+ }
+ .heading,
+ .small,
+ .no-indent {
+ text-indent: 0;
+ }
+ .small:not(.spacebreak),
+ .no-indent {
+ margin-left: -25px;
+ }
+ .spacebreak {
+ display: block;
+ margin-top: 25px;
+
+ &.no-indent {
+ margin-left: 0;
+ }
+ }
+ }
+}
diff --git a/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.spec.ts
new file mode 100644
index 000000000..453806044
--- /dev/null
+++ b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.spec.ts
@@ -0,0 +1,321 @@
+import { DebugElement } from '@angular/core';
+import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { lastValueFrom, Observable, of as observableOf, ReplaySubject } from 'rxjs';
+import Spy = jasmine.Spy;
+
+import { clickAndAwaitChanges } from '@testing/click-helper';
+import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper';
+import {
+ expectSpyCall,
+ expectToBe,
+ expectToContain,
+ expectToEqual,
+ getAndExpectDebugElementByCss,
+} from '@testing/expect-helper';
+import { mockEditionData } from '@testing/mock-data';
+
+import { CompileHtmlComponent } from '@awg-shared/compile-html';
+import { EDITION_GLYPHS_DATA } from '@awg-views/edition-view/data';
+import { PrefaceList } from '@awg-views/edition-view/models';
+import { EditionDataService, EditionService } from '@awg-views/edition-view/services';
+
+import { EditionPrefaceComponent } from './edition-preface.component';
+
+describe('EditionPrefaceComponent (DONE)', () => {
+ let component: EditionPrefaceComponent;
+ let fixture: ComponentFixture;
+ let compDe: DebugElement;
+
+ let getGlyphSpy: Spy;
+ let setLanguageSpy: Spy;
+ let editionServiceUpdateIsPrefaceViewSpy: Spy;
+ let editionServiceClearIsPrefaceViewSpy: Spy;
+ let editionDataServiceGetPrefaceDataSpy: Spy;
+
+ let mockEditionService: Partial;
+ let mockEditionDataService: Partial;
+ let mockIsPrefaceViewSubject: ReplaySubject;
+
+ let expectedPrefaceData: PrefaceList;
+
+ beforeEach(async () => {
+ mockIsPrefaceViewSubject = new ReplaySubject(1);
+
+ mockEditionService = {
+ updateIsPrefaceView: (isView: boolean): void => mockIsPrefaceViewSubject.next(isView),
+ clearIsPrefaceView: (): void => mockIsPrefaceViewSubject.next(null),
+ };
+
+ mockEditionDataService = {
+ getEditionPrefaceData: (): Observable => observableOf(expectedPrefaceData),
+ };
+
+ await TestBed.configureTestingModule({
+ declarations: [CompileHtmlComponent, EditionPrefaceComponent],
+ providers: [
+ { provide: EditionService, useValue: mockEditionService },
+ { provide: EditionDataService, useValue: mockEditionDataService },
+ ],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditionPrefaceComponent);
+ component = fixture.componentInstance;
+ compDe = fixture.debugElement;
+
+ mockEditionService = TestBed.inject(EditionService);
+ mockEditionDataService = TestBed.inject(EditionDataService);
+
+ // Test data
+ expectedPrefaceData = JSON.parse(JSON.stringify(mockEditionData.mockPrefaceData));
+
+ // Spies on component functions
+ // `.and.callThrough` will track the spy down the nested describes, see
+ // https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3Eand.callThrough%3C/code%3E
+ getGlyphSpy = spyOn(component, 'getGlyph').and.callThrough();
+ setLanguageSpy = spyOn(component, 'setLanguage').and.callThrough();
+ editionServiceUpdateIsPrefaceViewSpy = spyOn(mockEditionService, 'updateIsPrefaceView').and.callThrough();
+ editionServiceClearIsPrefaceViewSpy = spyOn(mockEditionService, 'clearIsPrefaceView').and.callThrough();
+ editionDataServiceGetPrefaceDataSpy = spyOn(mockEditionDataService, 'getEditionPrefaceData').and.callThrough();
+ });
+
+ it('... should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('BEFORE initial data binding', () => {
+ it('... should not have `prefaceData$`', () => {
+ expect(component.prefaceData$).toBeUndefined();
+ });
+
+ it('... should have `currentLanguage` = 0', () => {
+ expectToBe(component.currentLanguage, 0);
+ });
+
+ it('... should have `GLYPHS`', () => {
+ expectToEqual(component.GLYPHS, EDITION_GLYPHS_DATA);
+ });
+
+ it('... should have `ref`', () => {
+ expectToEqual(component.ref, component);
+ });
+
+ it('... should not have called EditionService', () => {
+ expectSpyCall(editionServiceUpdateIsPrefaceViewSpy, 0);
+ });
+
+ it('... should not have called EditionDataService', () => {
+ expectSpyCall(editionDataServiceGetPrefaceDataSpy, 0);
+ });
+
+ describe('VIEW', () => {
+ it('... should contain no outer div.row (yet)', () => {
+ getAndExpectDebugElementByCss(compDe, 'div.row', 0, 0);
+ });
+ });
+ });
+
+ describe('AFTER initial data binding', () => {
+ beforeEach(() => {
+ // Trigger initial data binding
+ fixture.detectChanges();
+ });
+
+ it('... should have updated IsPrefaceViewFlag (via EditionService)', () => {
+ expectSpyCall(editionServiceUpdateIsPrefaceViewSpy, 1, true);
+ });
+
+ it('... should have called EditionDataService', () => {
+ expectSpyCall(editionDataServiceGetPrefaceDataSpy, 1);
+ });
+
+ it('... should have prefaceData$', waitForAsync(() => {
+ expectAsync(lastValueFrom(component.prefaceData$)).toBeResolved();
+ expectAsync(lastValueFrom(component.prefaceData$)).toBeResolvedTo(expectedPrefaceData);
+ }));
+
+ describe('VIEW', () => {
+ it('... should contain 1 outer div.awg-preface-view', () => {
+ getAndExpectDebugElementByCss(compDe, 'div.awg-preface-view', 1, 1);
+ });
+
+ it('... should contain 1 language-switcher paragraph', () => {
+ getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ });
+
+ it('... should contain 2 language-switcher anchor elements (DE | EN)', () => {
+ const pDes = getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ const pEl = pDes[0].nativeElement;
+
+ expectToBe(pEl.textContent, 'DE | EN');
+
+ const aDes = getAndExpectDebugElementByCss(pDes[0], 'a', 2, 2);
+ const aEl1 = aDes[0].nativeElement;
+ const aEl2 = aDes[1].nativeElement;
+
+ expectToBe(aEl1.textContent, 'DE');
+ expectToBe(aEl2.textContent, 'EN');
+ });
+
+ it('... should trigger `setLanguage` method on anchor click', fakeAsync(() => {
+ const pDes = getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ const aDes = getAndExpectDebugElementByCss(pDes[0], 'a', 2, 2);
+
+ // Trigger click with click helper & wait for changes
+ clickAndAwaitChanges(aDes[0], fixture);
+
+ expectSpyCall(setLanguageSpy, 1);
+
+ // Trigger click with click helper & wait for changes
+ clickAndAwaitChanges(aDes[1], fixture);
+
+ expectSpyCall(setLanguageSpy, 2);
+ }));
+
+ it('... should set currentLanguage to 0 when clicking on first anchor', fakeAsync(() => {
+ const pDes = getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ const aDes = getAndExpectDebugElementByCss(pDes[0], 'a', 2, 2);
+
+ // Click on first anchor
+ clickAndAwaitChanges(aDes[0], fixture);
+
+ expectToBe(component.currentLanguage, 0);
+ }));
+
+ it('... should set currentLanguage to 1 when clicking on second anchor', fakeAsync(() => {
+ const pDes = getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ const aDes = getAndExpectDebugElementByCss(pDes[0], 'a', 2, 2);
+
+ // Click on second anchor
+ clickAndAwaitChanges(aDes[1], fixture);
+
+ expectToBe(component.currentLanguage, 1);
+ }));
+
+ it('... should have .active class on first anchor element when currentLanguage is 0', fakeAsync(() => {
+ const pDes = getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ const aDes = getAndExpectDebugElementByCss(pDes[0], 'a', 2, 2);
+
+ // Click on first anchor
+ clickAndAwaitChanges(aDes[0], fixture);
+
+ const aEl0 = aDes[0].nativeElement;
+ const aEl1 = aDes[1].nativeElement;
+
+ expectToContain(aEl0.classList, 'active');
+ expect(aEl1.classList).not.toContain('active');
+ }));
+
+ it('... should have .active class on second anchor element when currentLanguage is 1', fakeAsync(() => {
+ const pDes = getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ const aDes = getAndExpectDebugElementByCss(pDes[0], 'a', 2, 2);
+
+ // Click on second anchor
+ clickAndAwaitChanges(aDes[1], fixture);
+
+ const aEl0 = aDes[0].nativeElement;
+ const aEl1 = aDes[1].nativeElement;
+
+ expect(aEl0.classList).not.toContain('active');
+ expectToContain(aEl1.classList, 'active');
+ }));
+
+ it('... should contain as many preface paragraph elements in div.awg-preface-view as content items in preview data (german)', () => {
+ // Div debug element
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div.awg-preface-view', 1, 1);
+
+ getAndExpectDebugElementByCss(
+ divDes[0],
+ 'p.awg-preface-para',
+ expectedPrefaceData.preface[0].content.length,
+ expectedPrefaceData.preface[0].content.length
+ );
+ });
+
+ it('... should contain as many preface paragraph elements in div.awg-preface-view as content items in preview data (english)', () => {
+ // Div debug element
+ const divDes = getAndExpectDebugElementByCss(compDe, 'div.awg-preface-view', 1, 1);
+
+ getAndExpectDebugElementByCss(
+ divDes[0],
+ 'p.awg-preface-para',
+ expectedPrefaceData.preface[1].content.length,
+ expectedPrefaceData.preface[1].content.length
+ );
+ });
+ });
+
+ describe('#getGlyph()', () => {
+ it('... should have a method `getGlyph`', () => {
+ expect(component.getGlyph).toBeDefined();
+ });
+
+ it('... should trigger on change detection', () => {
+ expectSpyCall(getGlyphSpy, 2);
+
+ detectChangesOnPush(fixture);
+
+ expectSpyCall(getGlyphSpy, 3);
+ });
+
+ it('... should return the correct hex value for a valid glyph alt value', () => {
+ expectToBe(component.getGlyph('[bb]'), '\uD834\uDD2B'); // DOUBLE_FLAT
+ expectToBe(component.getGlyph('[x]'), '\uD834\uDD2A'); // DOUBLE_SHARP
+ expectToBe(component.getGlyph('[b]'), '\u266D'); // FLAT
+ expectToBe(component.getGlyph('[#]'), '\u266F'); // SHARP
+ expectToBe(component.getGlyph('[a]'), '\u266E'); // NATURAL
+ expectToBe(component.getGlyph('[f]'), '\uD834\uDD91'); // FORTE
+ expectToBe(component.getGlyph('[ped]'), '\uD834\uDDAE'); // PEDAL
+ });
+
+ it('... should return an empty string for an invalid glyph alt value', () => {
+ expectToBe(component.getGlyph(''), '');
+ expectToBe(component.getGlyph('[invalid]'), '');
+ expectToBe(component.getGlyph('[not found]'), '');
+ });
+ });
+
+ describe('#setLanguage()', () => {
+ it('... should have a method `setLanguage`', () => {
+ expect(component.setLanguage).toBeDefined();
+ });
+
+ it('... should trigger on click', fakeAsync(() => {
+ const pDes = getAndExpectDebugElementByCss(compDe, 'p.awg-language-switcher', 1, 1);
+ const aDes = getAndExpectDebugElementByCss(pDes[0], 'a', 2, 2);
+
+ // Trigger click with click helper & wait for changes
+ clickAndAwaitChanges(aDes[0], fixture);
+
+ expectSpyCall(setLanguageSpy, 1);
+
+ // Trigger click with click helper & wait for changes
+ clickAndAwaitChanges(aDes[1], fixture);
+
+ expectSpyCall(setLanguageSpy, 2);
+ }));
+
+ it('... should set the currentLanguage to 0 when called with 0', () => {
+ component.setLanguage(0);
+
+ expectToBe(component.currentLanguage, 0);
+ });
+
+ it('... should set the currentLanguage to 1 when called with 1', () => {
+ component.setLanguage(1);
+
+ expectToBe(component.currentLanguage, 1);
+ });
+ });
+
+ describe('#ngOnDestroy()', () => {
+ it('... should have cleared isPrefaceView$ on destroy (via EditionService)', () => {
+ component.ngOnDestroy();
+
+ expectSpyCall(editionServiceClearIsPrefaceViewSpy, 1);
+ });
+ });
+ });
+});
diff --git a/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.ts b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.ts
new file mode 100644
index 000000000..21bc53b7b
--- /dev/null
+++ b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.component.ts
@@ -0,0 +1,109 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Observable } from 'rxjs';
+
+import { EDITION_GLYPHS_DATA } from '@awg-views/edition-view/data';
+import { PrefaceList } from '@awg-views/edition-view/models';
+import { EditionDataService, EditionService } from '@awg-views/edition-view/services';
+
+/**
+ * The EditionPreface component.
+ *
+ * It contains the preface section
+ * of the edition view of the app.
+ */
+@Component({
+ selector: 'awg-edition-preface',
+ templateUrl: './edition-preface.component.html',
+ styleUrls: ['./edition-preface.component.scss'],
+})
+export class EditionPrefaceComponent implements OnInit, OnDestroy {
+ /**
+ * Public variable: prefaceData$.
+ *
+ * It keeps an observable of the data of the edition preface.
+ */
+ prefaceData$: Observable;
+
+ /**
+ * Public variable: currentLanguage.
+ *
+ * It keeps the current language of the edition preface: 0 for German, 1 for English.
+ */
+ currentLanguage = 0;
+
+ /**
+ * Readonly variable: GLYPHS.
+ *
+ * It keeps the data for musical glyphs.
+ */
+ readonly GLYPHS = EDITION_GLYPHS_DATA;
+
+ /**
+ * Self-referring variable needed for CompileHtml library.
+ */
+ ref: EditionPrefaceComponent;
+
+ /**
+ * Constructor of the EditionPrefaceComponent.
+ *
+ * It declares private instances of the EditionService and EditionDataService
+ * and the self-referring ref variable needed for CompileHtml library.
+ *
+ * @param {EditionService} editionService Instance of the EditionService.
+ * @param {EditionDataService} editionDataService Instance of the EditionDataService.
+ */
+ constructor(
+ private editionService: EditionService,
+ private editionDataService: EditionDataService
+ ) {
+ this.ref = this;
+ }
+
+ /**
+ * Angular life cycle hook: ngOnInit.
+ *
+ * It calls the containing methods
+ * when initializing the component.
+ */
+ ngOnInit(): void {
+ this.editionService.updateIsPrefaceView(true);
+ this.prefaceData$ = this.editionDataService.getEditionPrefaceData();
+ }
+
+ /**
+ * Public method: getGlyph.
+ *
+ * It returns the hex value string for a glyph referenced by the given glyph string.
+ *
+ * @param {string} glyphString The given glyph string.
+ * @returns {string} The hex value string of the given glyph string or empty string.
+ */
+ getGlyph(glyphString: string): string {
+ const glyph = Object.values(this.GLYPHS).find(g => g.alt === glyphString);
+ return glyph ? glyph.hex : '';
+ }
+
+ /**
+ * Public method: setLanguage.
+ *
+ * It sets the current language of the edition preface.
+ *
+ * @param {number} language The given language number.
+ * @returns {void} Sets the current language.
+ */
+ setLanguage(language: number): void {
+ this.currentLanguage = language;
+ }
+
+ /**
+ * Angular life cycle hook: ngOnDestroy.
+ *
+ * It calls the containing methods
+ * when destroying the component.
+ *
+ * Destroys subscriptions.
+ */
+ ngOnDestroy() {
+ this.editionService.clearIsPrefaceView();
+ }
+}
diff --git a/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.module.ts b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.module.ts
new file mode 100644
index 000000000..b09afe66c
--- /dev/null
+++ b/src/app/views/edition-view/edition-outlets/edition-preface/edition-preface.module.ts
@@ -0,0 +1,18 @@
+import { NgModule } from '@angular/core';
+
+import { SharedModule } from '@awg-shared/shared.module';
+
+import { EditionPrefaceRoutingModule, routedEditionPrefaceComponents } from './edition-preface-routing.module';
+
+/**
+ * The EditionPreface module.
+ *
+ * It embeds the {@link EditionPrefaceComponent} and its
+ * [routing definition]{@link EditionPrefaceRoutingModule}
+ * as well as the {@link SharedModule}.
+ */
+@NgModule({
+ imports: [SharedModule, EditionPrefaceRoutingModule],
+ declarations: [routedEditionPrefaceComponents],
+})
+export class EditionPrefaceModule {}
diff --git a/src/app/views/edition-view/edition-outlets/edition-preface/index.ts b/src/app/views/edition-view/edition-outlets/edition-preface/index.ts
new file mode 100644
index 000000000..090e04721
--- /dev/null
+++ b/src/app/views/edition-view/edition-outlets/edition-preface/index.ts
@@ -0,0 +1 @@
+export * from './edition-preface.component';
diff --git a/src/app/views/edition-view/edition-outlets/edition-row-tables/edition-row-tables.component.html b/src/app/views/edition-view/edition-outlets/edition-row-tables/edition-row-tables.component.html
index 6b00e4903..72a4ba5a9 100644
--- a/src/app/views/edition-view/edition-outlets/edition-row-tables/edition-row-tables.component.html
+++ b/src/app/views/edition-view/edition-outlets/edition-row-tables/edition-row-tables.component.html
@@ -2,7 +2,7 @@
@for (rowTable of rowTablesData?.rowTables; track rowTable) {