{"id":614,"date":"2015-10-15T09:32:09","date_gmt":"2015-10-15T07:32:09","guid":{"rendered":"http:\/\/blog.thecodecampus.de\/?p=614"},"modified":"2023-12-20T20:12:08","modified_gmt":"2023-12-20T19:12:08","slug":"structured-protractor-end-to-end-tests","status":"publish","type":"post","link":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/","title":{"rendered":"Structured End-To-End Tests With Protractor"},"content":{"rendered":"<p lang=\"en-US\">The Angular team provides a tool set for creating end to end tests (e2e) called protractor <a href=\"http:\/\/www.protractortest.org\/\">http:\/\/www.protractortest.org<\/a> based on WebDriver from Selenium. It&#8217;s extended by a deferred element finder and support for the ng-model notation, so it could be the ideal partner for testing AngularJS applications. But if wishes were horses, beggars would ride.<!--more--><\/p>\n<p lang=\"en-US\">E2E tests in real life projects tend to be messy. In my opinion this is caused by two reasons. At first, when using a back-end service in this kind of testing, there&#8217;s the problem how to reset it&#8217;s state, most commonly a data base, to a well defined starting condition. Second, I observe that changes on user interfaces occur more often than in the back-end. So the task of writing user interface navigation in your tests gets similar to pushing Sysiphus&#8217; stone up the hill only to watch it rolling down when someone in your team changes the HTML in a minor way, e.g. embedding additional &lt;div&gt; or changing an id. In this article only the later issue will be discussed. Protractor might be the wrong tool for solving the first issue. Though not analyzed, it may be easier using the Java based Selenium Web-Driver, not because it&#8217;s better, but resetting the data base to defined state using the back-end tool set might be more efficient than re-implementing it using node.js, as long as node.js isn&#8217;t used as back-end technology of course.<\/p>\n<p lang=\"en-US\">Instead of writing another protractor tutorial, the <a href=\"https:\/\/angular.github.io\/protractor\/#\/tutorial\">official one<\/a>\u00a0is used, but structured differently by using something I call an\u00a0<i>user interface API<\/i>. There might be a better or an official name, but let&#8217;s just call it UI API. The intention should be clear. Instead of developing only the user interface for the end user, it should be considered to develop and deliver an API to access all portions of the UI. Especially in an environment with multiple back-end systems it&#8217;s easier to abstract to common language than to speak in different \u201clanguages\u201d of the UI. For example the UI of a car dealer might consist of three modules: security, product configuration and financing, developed by different teams with different technologies. So instead of writing (in pseudo code) something like the following:<\/p>\n<pre class=\"lang:js decode:true\" title=\"Selenium Simple Approach\">driver.get(\"http:\/\/www.mycardealer.com\/login\")\r\nuser = driver.findElements(By.id(\"username\"));\r\npass = driver.findElements(By.id(\"passwd\"));\r\nbutton = driver.findElements(By.id(\"login\"));\r\nuser.sendKeys('test');\r\npass.sendKeys('test');\r\nbutton.click();\r\ndriver.get(\"http:\/\/www.mycardealer.com\/cars\")\r\ncar = driver.findElement(By.partialLinkText(\"Model Foo\"));\r\ncar.click();<\/pre>\n<p>&nbsp;<\/p>\n<p lang=\"en-US\">the developer of the login user interface could just provide login and business functions to abstract the details away. Even more important, there is contract between the tester and the developer how to access a specific portion of the UI. In this example \u201cModel Foo\u201d depends tightly on the locale. The developer can&#8217;t know, which locale the tester uses. Therefore the developer might put more information on it&#8217;s own getting the page more testable.<\/p>\n<p lang=\"en-US\">But why not using <a href=\"http:\/\/www.seleniumhq.org\/projects\/ide\/\">Selenium IDE<\/a> instead of this abstract contract? After spending several months using the Selenium IDE in former project the following happened:<\/p>\n<ol>\n<li>\n<p lang=\"en-US\">The IDE did not record the events we wanted to, so we had to change it a bit<\/p>\n<\/li>\n<li>\n<p lang=\"en-US\">Test implemented, everything o.k.<\/p>\n<\/li>\n<li><span lang=\"en-US\">Several days later changes in the UI broke the test. <\/span><span lang=\"en-US\">Tried<\/span><span lang=\"en-US\"> replay <\/span><span lang=\"en-US\">the test, but we forgot what exactly we were typing in the forms. So from now on we had Excel lists which described what and how to test.<\/span><\/li>\n<li>\n<p lang=\"en-US\">Recorded the test again but in the meantime we forgot how we changed the output<\/p>\n<\/li>\n<li>\n<p lang=\"en-US\">Instead of using the Selenium IDE abstractions of the UI actions were written, like login, addPartner, addContract&#8230;<\/p>\n<\/li>\n<li>\n<p lang=\"en-US\">\u2026 oh, there they are \u2026<\/p>\n<\/li>\n<\/ol>\n<p lang=\"en-US\">So soon or later you tend to create these <em>UI verbs<\/em>. But in my humble opinion the UI developer should take care of them, instead of the integration tester.<\/p>\n<p lang=\"en-US\"><strong>Extract and define the UI contract<\/strong><\/p>\n<p lang=\"en-US\">The following example should demonstrate extracting the \u201c<em>verbs<\/em>\u201d into one or more\u00a0self-contained\u00a0module. It is available on Github, of course: <a href=\"https:\/\/github.com\/dzuvic\/structured-protractor-example\">https:\/\/github.com\/dzuvic\/structured-protractor-example<\/a>.<\/p>\n<p lang=\"en-US\">To use Protractor it needs to be configured. The bare minimum with a base URL looks like this:<\/p>\n<pre class=\"lang:js decode:true\" title=\"Simple Protractor configuration\">exports.config = {\r\n  framework: 'jasmine2',\r\n  seleniumAddress: 'http:\/\/localhost:4444\/wd\/hub',\r\n  baseUrl: 'http:\/\/juliemr.github.io',\r\n  specs: ['.\/spec\/**\/*.js']\r\n}<\/pre>\n<p lang=\"en-US\">Protractor supports several test frameworks, but we&#8217;ll concentrate on Jasmin, because it&#8217;s Protractor&#8217;s default test framework. In your own tests you should take care of the base URL. In some projects there&#8217;s a class of parameters, which are configured centrally. The base URL is typically one them and should be handled appropriately. In this example, the base URL is just defined in Protractor, so the helper module depends only on that.<\/p>\n<p lang=\"en-US\">When we take a look at the tutorial example of Protractor it looks like this:<\/p>\n<pre class=\"lang:default decode:true\" title=\"Simple Test taken from the tutorial\">describe('Protractor Demo App', function() {\r\n  it('should add one and two', function() {\r\n    browser.get('http:\/\/juliemr.github.io\/protractor-demo\/');\r\n    element(by.model('first')).sendKeys(1);\r\n    element(by.model('second')).sendKeys(2);\r\n    element(by.id('gobutton')).click();\r\n    expect(element(by.binding('latest')).getText()).\r\n        toEqual('3');\r\n  });\r\n});<\/pre>\n<p>&nbsp;<\/p>\n<p lang=\"en-US\">All we have to do is to extract the defined functions in an own helper module. First of all a helper module, that contains the \u201c<em>UI verbs<\/em>\u201d has to be defined. In the end it looks like this:<\/p>\n<pre class=\"lang:js decode:true \" title=\"UI contract: Test helper module\">var browser = {};\r\nvar element = function () {};\r\nmodule.exports = {\r\n    available: function () {\r\n        return true;\r\n    },\r\n    init: function (thatBrowser, thatElement) {\r\n        browser = thatBrowser;\r\n        element = thatElement;\r\n        browser.get('\/protractor-demo\/');\r\n    },\r\n    getTitle: function () {\r\n        return browser.getTitle();\r\n    },\r\n    add: function (a, b) {\r\n        var firstNumber = element(by.model('first'));\r\n        var secondNumber = element(by.model('second'));\r\n        var goButton = element(by.id('gobutton'));\r\n        var latestResult = element(by.binding('latest'));\r\n        firstNumber.sendKeys(a);\r\n        secondNumber.sendKeys(b);\r\n        goButton.click();\r\n        return latestResult.getText();\r\n    },\r\n    history: function() {\r\n        var history = element.all(by.repeater('result in memory'));\r\n        return history;\r\n    }\r\n};<\/pre>\n<p>&nbsp;<\/p>\n<p lang=\"en-US\">The Jasmin test uses this helper module:<\/p>\n<pre class=\"lang:js decode:true \" title=\"Jasmin test using the UI contract\">var demoHelper = require('..\/..\/helper');\r\ndescribe('Protractor Demo App', function () {\r\n    beforeEach(function () {\r\n        demoHelper.init(browser, element);\r\n    });\r\n    it('add 5 + 5 = 10', function () {\r\n        expect(demoHelper.add(5, 5)).toEqual('10');\r\n    });\r\n    it('two additions in the history', function () {\r\n        expect(demoHelper.add(5, 5)).toEqual('10');\r\n        expect(demoHelper.add(1, 2)).toEqual('3');\r\n        expect(demoHelper.history().count()).toEqual(2)\r\n    });\r\n});<\/pre>\n<p>&nbsp;<\/p>\n<p lang=\"en-US\">Unfortunately the helper needs objects that Protractor initialized, so the module has to be initialized with them as well. This initialization happens each time when the page has to be loaded. A minor remark: The helper module is loaded with a relative path, which isn&#8217;t ideal. This could be avoided by creating it&#8217;s own npm module and publishing in a private repository.<\/p>\n<p lang=\"en-US\">To use this tests just execute the following:<\/p>\n<pre class=\"western\"><code class=\"western\">npm install <\/code> <code class=\"western\">.\/node_modules\/protractor\/bin\/webdriver-manager update<\/code> <code class=\"western\">.\/node_modules\/protractor\/bin\/webdriver-manager start<\/code> <code class=\"western\">.\/node_modules\/protractor\/bin\/protractor         <\/code><\/pre>\n<p lang=\"en-US\"><strong>Conclusion<\/strong><\/p>\n<p lang=\"en-US\">At this point it should be clear, that writing End-To-End tests gets ugly and hardly to maintain really fast if there isn&#8217;t a kind of contract between the UI and the tests. Putting this \u201ccontract\u201d into an exportable module, that the UI developer is responsible for, should keep the test code clean. In fact, this pattern isn&#8217;t new at all and is called \u201cSeparation of concerns\u201d and best described by none other than <a href=\"http:\/\/www.cs.utexas.edu\/users\/EWD\/transcriptions\/EWD04xx\/EWD447.html\">Edsger W. Dijkstra<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Angular team provides a tool set for creating end to end tests (e2e) called protractor http:\/\/www.protractortest.org based on WebDriver from Selenium. It&#8217;s extended by a deferred element finder and support for the ng-model notation, so it could be the ideal partner for testing AngularJS applications. But if wishes were horses, beggars would ride.<\/p>\n","protected":false},"author":29,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,2,78],"tags":[62,61],"class_list":["post-614","post","type-post","status-publish","format-standard","hentry","category-angularjs","category-javascript","category-testing","tag-angularjs","tag-javascript"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Structured End-To-End Tests With Protractor - Web Development Blog<\/title>\n<meta name=\"description\" content=\"How to structure protractor e2e test in a clean way.Optimize Protractor e2e tests with a clean structure. Learn efficient organization for streamlined workflows. Elevate your test architecture now!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Structured End-To-End Tests With Protractor - Web Development Blog\" \/>\n<meta property=\"og:description\" content=\"How to structure protractor e2e test in a clean way.Optimize Protractor e2e tests with a clean structure. Learn efficient organization for streamlined workflows. Elevate your test architecture now!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Development tips and tricks - theCodeCampus Blog\" \/>\n<meta property=\"article:published_time\" content=\"2015-10-15T07:32:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-20T19:12:08+00:00\" \/>\n<meta name=\"author\" content=\"theCodeCampus\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"theCodeCampus\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/\"},\"author\":{\"name\":\"theCodeCampus\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/person\\\/276bbda2f8da73154f22fb652201cfbc\"},\"headline\":\"Structured End-To-End Tests With Protractor\",\"datePublished\":\"2015-10-15T07:32:09+00:00\",\"dateModified\":\"2023-12-20T19:12:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/\"},\"wordCount\":959,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#organization\"},\"keywords\":[\"AngularJS\",\"JavaScript\"],\"articleSection\":[\"AngularJS 1\",\"JavaScript\",\"Testing\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/\",\"name\":\"Structured End-To-End Tests With Protractor - Web Development Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#website\"},\"datePublished\":\"2015-10-15T07:32:09+00:00\",\"dateModified\":\"2023-12-20T19:12:08+00:00\",\"description\":\"How to structure protractor e2e test in a clean way.Optimize Protractor e2e tests with a clean structure. Learn efficient organization for streamlined workflows. Elevate your test architecture now!\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/structured-protractor-end-to-end-tests\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Structured End-To-End Tests With Protractor\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/\",\"name\":\"Web Development tips and tricks - theCodeCampus Blog\",\"description\":\"Tips, tricks, and experiences about developing web and mobile applications with Angular, TypeScript, and Testing.\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#organization\",\"name\":\"theCodeCampus\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/TCC-Logo-Bildmarke-quadratisch.jpg\",\"contentUrl\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/TCC-Logo-Bildmarke-quadratisch.jpg\",\"width\":156,\"height\":156,\"caption\":\"theCodeCampus\"},\"image\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/person\\\/276bbda2f8da73154f22fb652201cfbc\",\"name\":\"theCodeCampus\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/TCC-Logo-Bildmarke-quadratisch-96x96.jpg\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/TCC-Logo-Bildmarke-quadratisch-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/TCC-Logo-Bildmarke-quadratisch-96x96.jpg\",\"caption\":\"theCodeCampus\"},\"description\":\"Our knowledge is not simply gained through reading - it is trained, tested and constantly being expanded. Because first and foremost, we are all developers at W11K. The know-how that we acquire here as developers, consultants and information architects flows immediately into our training courses and articles for theCodeCampus.\",\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/showcase\\\/thecodecampus\\\/\"],\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/author\\\/admin\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Structured End-To-End Tests With Protractor - Web Development Blog","description":"How to structure protractor e2e test in a clean way.Optimize Protractor e2e tests with a clean structure. Learn efficient organization for streamlined workflows. Elevate your test architecture now!","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/","og_locale":"en_US","og_type":"article","og_title":"Structured End-To-End Tests With Protractor - Web Development Blog","og_description":"How to structure protractor e2e test in a clean way.Optimize Protractor e2e tests with a clean structure. Learn efficient organization for streamlined workflows. Elevate your test architecture now!","og_url":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/","og_site_name":"Web Development tips and tricks - theCodeCampus Blog","article_published_time":"2015-10-15T07:32:09+00:00","article_modified_time":"2023-12-20T19:12:08+00:00","author":"theCodeCampus","twitter_card":"summary_large_image","twitter_misc":{"Written by":"theCodeCampus","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/#article","isPartOf":{"@id":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/"},"author":{"name":"theCodeCampus","@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/person\/276bbda2f8da73154f22fb652201cfbc"},"headline":"Structured End-To-End Tests With Protractor","datePublished":"2015-10-15T07:32:09+00:00","dateModified":"2023-12-20T19:12:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/"},"wordCount":959,"commentCount":0,"publisher":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#organization"},"keywords":["AngularJS","JavaScript"],"articleSection":["AngularJS 1","JavaScript","Testing"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/","url":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/","name":"Structured End-To-End Tests With Protractor - Web Development Blog","isPartOf":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#website"},"datePublished":"2015-10-15T07:32:09+00:00","dateModified":"2023-12-20T19:12:08+00:00","description":"How to structure protractor e2e test in a clean way.Optimize Protractor e2e tests with a clean structure. Learn efficient organization for streamlined workflows. Elevate your test architecture now!","breadcrumb":{"@id":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.thecodecampus.de\/blog\/structured-protractor-end-to-end-tests\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.thecodecampus.de\/blog\/"},{"@type":"ListItem","position":2,"name":"Structured End-To-End Tests With Protractor"}]},{"@type":"WebSite","@id":"https:\/\/www.thecodecampus.de\/blog\/#website","url":"https:\/\/www.thecodecampus.de\/blog\/","name":"Web Development tips and tricks - theCodeCampus Blog","description":"Tips, tricks, and experiences about developing web and mobile applications with Angular, TypeScript, and Testing.","publisher":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.thecodecampus.de\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.thecodecampus.de\/blog\/#organization","name":"theCodeCampus","url":"https:\/\/www.thecodecampus.de\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/01\/TCC-Logo-Bildmarke-quadratisch.jpg","contentUrl":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/01\/TCC-Logo-Bildmarke-quadratisch.jpg","width":156,"height":156,"caption":"theCodeCampus"},"image":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/person\/276bbda2f8da73154f22fb652201cfbc","name":"theCodeCampus","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/01\/TCC-Logo-Bildmarke-quadratisch-96x96.jpg","url":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/01\/TCC-Logo-Bildmarke-quadratisch-96x96.jpg","contentUrl":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/01\/TCC-Logo-Bildmarke-quadratisch-96x96.jpg","caption":"theCodeCampus"},"description":"Our knowledge is not simply gained through reading - it is trained, tested and constantly being expanded. Because first and foremost, we are all developers at W11K. The know-how that we acquire here as developers, consultants and information architects flows immediately into our training courses and articles for theCodeCampus.","sameAs":["https:\/\/www.linkedin.com\/showcase\/thecodecampus\/"],"url":"https:\/\/www.thecodecampus.de\/blog\/author\/admin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts\/614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/comments?post=614"}],"version-history":[{"count":15,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts\/614\/revisions"}],"predecessor-version":[{"id":2722,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts\/614\/revisions\/2722"}],"wp:attachment":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/media?parent=614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/categories?post=614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/tags?post=614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}