Best Choice concept strategie New Update

You are viewing this post: Best Choice concept strategie New Update

Neues Update zum Thema concept strategie


Samen de stap maken – Regionale Energiestrategie Twente Aktualisiert

Concept RES Twente. juli 2021 RES 1.0: strategische koers. december 2021 Transitievisies Warmte. 2021 – 2023 Samen aan de slag. juli 2023 RES Twente 2.0. 2030 1,5 TWh en Regionale Structuur Warmte. 2050 Klimaatneutraal. De tijdlijn: verleden, heden en …

+ Details hier sehen

Read more

Ster in samen duurzaam in Haaksbergen

Er geboren al ontzettend veel in der gleichen Region wie der Stap te made om duurzame Energie op te wekken en alternatieven voor warmed te vinden

Kijkt du mee?

Die am häufigsten nachgefragte Anfrage

Inspraak en besluitvorming Wie werden regionale Energiestrategien in der Region entwickelt? Inspraak en besluitvorming Was ist die Zeitplanung?

Inspraak en besluitvorming How wordt de omgeving betrokken?

Technische Qualität und Systemeffizienz/Wirtschaftlichkeit Wie ist die technische Qualität?

Strategie \u0026 concept Update New

Video ansehen

Weitere Informationen zum Thema concept strategie

concept strategie Ähnliche Bilder im Thema

 Update  Strategie \u0026 concept
Strategie \u0026 concept New Update

Unternehmensberatung für Markenkommunikation. – CONCEPT X Neueste

Wir bei CONCEPT X haben erkannt, dass dieser Dualismus aus Qualität und Emotion genau den Puls unserer Zeit trifft. Die Frage nach dem „Warum“ wird sich künftig als Herzstück erfolgreicher Kommunikation und Wegweiser für unternehmerisches Handeln erweisen.

+ ausführliche Artikel hier sehen

Read more

Organisation & Haltung

„Bei der digitalen Transformation steht wieder der Mensch im Mittelpunkt.“ Ich glaube an Marken, die Sinn machen!

Marken erwecken Vertrauen, wenn ein gutes Produkt dahinter steht – und ein tiefes Verständnis für die Beweggründe unseres Gegenübers

Wir von CONCEPT X haben erkannt, dass diese Dualität von Qualität und Emotion am Puls unserer Zeit ist

Die Frage nach dem „Warum“ wird sich in Zukunft als Herzstück erfolgreicher Kommunikation und als Wegweiser für unternehmerisches Handeln erweisen

Authentizität ist der Schlüssel zu einer einzigartigen, konsistenten und wertschöpfenden Haltung, die bei Ihren Zielgruppen Bestand hat

Wer seine Haltung neu definiert, verändert die bestehende Organisation

Sie wird ganzheitlicher, digitaler und agiler

Unverändert bleibt: Der Mensch steht im Mittelpunkt unserer Transformationsprojekte

Eine offene Denkweise in Bezug auf New Work und Leadership sowie Sensibilität gepaart mit empathischer Effizienz sind für mich in der Zusammenarbeit unerlässlich

mehr erfahren

Speltheorie: basis simultaan spel – dominante strategie en evenwicht (economie uitleg) Update

Video ansehen

Neues Update zum Thema concept strategie

concept strategie Einige Bilder im Thema

 Update  Speltheorie: basis simultaan spel - dominante strategie en evenwicht (economie uitleg)
Speltheorie: basis simultaan spel – dominante strategie en evenwicht (economie uitleg) Update

Network Requests | Cypress Documentation Neueste

Real World Example. The Cypress Real World App (RWA) end-to-end tests predominately rely on server responses, and only stub network responses on a few occasions to conveniently create edge-case or hard-to-create application states. This practice allows the project to achieve full code-coverage for the front end and back end of the app, but this has also required creating …

+ hier mehr lesen

Read more

Was Sie lernen werden Wie Cypress es Ihnen ermöglicht, das Backend mit cy.intercept() auszublenden

Welche Kompromisse wir eingehen, wenn wir unsere Netzwerkanfragen abbrechen

Wie Cypress die Netzwerkverwaltung im Befehlsprotokoll visualisiert

Wie man Aliase verwendet, um auf Anfragen zurückzugreifen und auf sie zu warten

Wie man deklarative Tests schreibt, die Flake widerstehen

Hinweis: Wenn Sie nach einer Ressource suchen, um eine HTTP-Anfrage zu stellen, werfen Sie einen Blick auf cy.request()

Teststrategien

Cypress unterstützt Sie beim Testen des gesamten Lebenszyklus von HTTP-Anforderungen innerhalb Ihrer Anwendung

Cypress bietet Ihnen Zugriff auf die Objekte mit Informationen über die Anforderung, sodass Sie Aussagen über ihre Eigenschaften machen können

Zusätzlich können Sie sogar die Antwort einer Anfrage stubben und verspotten

Gängige Testszenarien:

Assertion auf den Text einer Anfrage

Assertion auf der URL einer Anfrage

Assertion auf den Headern einer Anfrage

See also  Best Choice gutschrift mit rechnung verrechnen Update New

Stubbing des Körpers einer Antwort

Stubbing des Statuscodes einer Antwort

Stubbing der Header einer Antwort

Verzögerung einer Antwort

Warten auf eine Antwort

Innerhalb von Cypress haben Sie die Möglichkeit zu wählen, ob Sie Antworten stumm schalten oder sie tatsächlich auf Ihren Server treffen lassen

Sie können innerhalb desselben Tests auch mischen und abgleichen, indem Sie sich dafür entscheiden, bestimmte Anfragen zu stubben, während Sie anderen erlauben, Ihren Server zu treffen

Lassen Sie uns beide Strategien untersuchen, warum Sie die eine gegen die andere verwenden würden und warum Sie regelmäßig beide verwenden sollten Serverantworten

Anfragen, die nicht gestubbt werden, erreichen tatsächlich Ihren Server

Indem Sie Ihre Antworten nicht abbrechen, schreiben Sie echte End-to-End-Tests

Dies bedeutet, dass Sie Ihre Anwendung genauso steuern, wie es ein echter Benutzer tun würde

Wenn Anforderungen nicht gestubbt werden, garantiert dies, dass der Vertrag zwischen Ihrem Client und Server ordnungsgemäß funktioniert Korrekte Daten in der richtigen Struktur, damit Ihr Client sie konsumieren kann

Es ist eine gute Idee, End-to-End-Tests rund um die kritischen Pfade Ihrer Anwendung durchzuführen

Dazu gehören in der Regel die Benutzeranmeldung, die Anmeldung oder andere kritische Pfade wie die Abrechnung

Da keine Antworten gestubbt werden, bedeutet dies, dass Ihr Server tatsächlich echte Antworten senden muss

Dies kann problematisch sein, da Sie möglicherweise vor jedem Test ein Seeding für eine Datenbank durchführen müssen, um den Status zu generieren

Wenn Sie beispielsweise die Paginierung testen, müssten Sie die Datenbank mit jedem Objekt ausstatten, das erforderlich ist, um diese Funktion in Ihrer Anwendung zu replizieren

Dies kann problematisch sein, da Sie möglicherweise vor jedem Test ein Seeding für eine Datenbank durchführen müssen, um den Status zu generieren

Wenn Sie beispielsweise die Paginierung testen, müssten Sie die Datenbank mit jedem Objekt ausstatten, das erforderlich ist, um diese Funktion in Ihrer Anwendung zu replizieren

Da echte Antworten jede einzelne Schicht Ihres Servers durchlaufen (Controller, Modelle, Ansichten usw.), sind die Tests oft viel langsamer als Stub-Antworten

Wenn Sie eine herkömmliche serverseitige Anwendung schreiben, bei der die meisten Antworten HTML sind, werden Sie haben wahrscheinlich nur wenige stumpfe Antworten

Die meisten modernen Anwendungen, die JSON bedienen, können Stubbing jedoch nutzen

Vorteile Eher in der Produktion zu arbeiten

Testen Sie die Abdeckung rund um Serverendpunkte

Hervorragend geeignet für traditionelles serverseitiges HTML-Rendering

Nachteile Erfordert Seeding-Daten

Viel langsamer

Grenzfälle schwieriger zu testen

Empfohlene Verwendung Sparsam verwenden

Ideal für die kritischen Pfade Ihrer Anwendung

Hilfreich, einen Test um den glücklichen Pfad eines Features herum zu haben

Stub-Antworten

Mit Stubbing-Antworten können Sie jeden Aspekt der Antwort steuern, einschließlich des Antworttexts , des Status , der Header und sogar der Netzwerkverzögerung

Stubbing ist extrem schnell, die meisten Antworten werden in weniger als 20 ms zurückgegeben

Stubbing-Antworten sind eine großartige Möglichkeit, die Daten zu kontrollieren, die an Ihren Client zurückgegeben werden

Sie müssen keine Arbeit auf dem Server ausführen

Ihre Anwendung hat keine Ahnung, dass ihre Anforderungen gestubbt werden, sodass keine Codeänderungen erforderlich sind

Vorteile Kontrolle über Antworttexte, Status und Header

Kann erzwingen, dass Antworten länger dauern, um eine Netzwerkverzögerung zu simulieren

Keine Codeänderungen an Ihrem Server- oder Clientcode

Schnelle Reaktionszeiten von < 20 ms

Nachteile Keine Garantie, dass Ihre Stub-Antworten mit den tatsächlichen Daten übereinstimmen, die der Server sendet

Keine Testabdeckung auf einigen Serverendpunkten

Nicht so nützlich, wenn Sie herkömmliches serverseitiges HTML-Rendering verwenden

Vorgeschlagene Verwendung für die überwiegende Mehrheit der Tests

Mischen und abgleichen, führen Sie in der Regel einen echten End-to-End-Test durch und kürzen Sie dann den Rest

Perfekt für JSON-APIs

Beispiel aus der realen Welt Die End-to-End-Tests der Real World App (RWA) von Cypress stützen sich hauptsächlich auf Serverantworten und Stub-Netzwerkantworten nur bei wenigen Gelegenheiten, um bequem Randfälle oder schwierig zu erstellende Anwendungszustände zu erstellen

Diese Vorgehensweise ermöglicht es dem Projekt, eine vollständige Codeabdeckung für das Front-End und das Back-End der App zu erreichen, aber dies erforderte auch die Erstellung komplizierter Datenbank-Seeding- oder Test-Data-Factory-Skripte, die geeignete Daten in Übereinstimmung mit der Geschäftslogik der App generieren können

Sehen Sie sich eine der Real World App-Testsuiten an, um die Netzwerkhandhabung von Cypress in Aktion zu sehen

Stubben

Mit Cypress können Sie eine Antwort abbrechen und den Hauptteil, den Status, die Header oder sogar die Verzögerung steuern

cy.intercept() wird verwendet, um das Verhalten von HTTP-Anforderungen zu steuern

Sie können den Hauptteil, den HTTP-Statuscode, die Header und andere Antwortmerkmale statisch definieren

Weitere Informationen und Beispiele zu Stubbing-Antworten finden Sie unter cy.intercept()

Routing

cy

abfangen ( { Methode : ‘GET’ , URL : ‘/users/*’ , } , [ ] )

See also  The Best danke das wünsche ich ihnen auch New Update

als ( ‘getUsers’ )

Wenn Sie cy.intercept() verwenden, um eine Route zu definieren, zeigt Cypress diese unter „Routes“ im Befehlsprotokoll an

Wenn ein neuer Test ausgeführt wird, stellt Cypress das Standardverhalten wieder her und entfernt alle Routen und Stubs

Eine vollständige Referenz der API und Optionen finden Sie in der Dokumentation für cy.intercept().

Fixtures

Ein Fixture ist ein fester Datensatz, der sich in einer Datei befindet, die in Ihren Tests verwendet wird

Der Zweck einer Testvorrichtung besteht darin, sicherzustellen, dass es eine bekannte und feste Umgebung gibt, in der Tests durchgeführt werden, damit die Ergebnisse wiederholbar sind

Auf Fixtures wird innerhalb von Tests zugegriffen, indem der Befehl cy.fixture() aufgerufen wird

Mit Cypress können Sie Netzwerkanfragen stubben und sofort mit Fixture-Daten antworten

Beim Stubben einer Antwort müssen Sie normalerweise potenziell große und komplexe JSON-Objekte verwalten

Mit Cypress können Sie Fixture-Syntax direkt in Antworten integrieren.

cy

abfangen ( ‘GET’ , ‘/activities/*’ , { Fixture : ‘activities.json’ } )

Organisieren

Cypress erstellt automatisch eine vorgeschlagene Ordnerstruktur für die Organisation Ihrer Geräte bei jedem neuen Projekt

Standardmäßig wird eine example.json-Datei erstellt, wenn Sie Ihr Projekt zu Cypress hinzufügen.

/cypress/fixtures/example.json

Ihre Geräte können in zusätzlichen Ordnern weiter organisiert werden

Sie könnten beispielsweise einen weiteren Ordner mit dem Namen Bilder erstellen und Bilder hinzufügen:

/cypress/fixtures/images/cats.png /cypress/fixtures/images/dogs.png /cypress/fixtures/images/birds.png

Um auf die Fixtures zuzugreifen, die im Ordner images verschachtelt sind, schließen Sie den Ordner in Ihren Befehl cy.fixture() ein.

cy

Halterung ( ‘images/dogs.png’ )

Warten Unabhängig davon, ob Sie Antworten stubben oder nicht, Cypress ermöglicht es Ihnen, deklarativ cy.wait() für Anfragen und ihre Antworten zu erhalten

Im folgenden Abschnitt wird ein Konzept verwendet, das als Aliasing bekannt ist

Wenn Sie neu bei Cypress sind, sollten Sie das vielleicht zuerst überprüfen

Hier ist ein Beispiel für Aliasing-Anforderungen und anschließendes Warten auf sie:

cy

abfangen (‘/activities/*’ , {fixture: ‘activities’ } ) )

as ( ‘getActivities’ ) cy

abfangen ( ‘/messages/*’ , {fix: ‘messages’ } )

as (‘getMessages’) cy

Besuchen Sie ( ‘http://localhost:8888/dashboard’ ) cy

warte ( [ ‘@getActivities’ , ‘@getMessages’ ] ) cy

bekomme(‘h1’)

sollte ( ‘enthalten’ , ‘Dashboard’ )

Wenn Sie die Antwortdaten jeder Antwort einer Alias-Route überprüfen möchten, können Sie mehrere cy.wait()-Aufrufe verwenden.

cy

abfangen ( { Methode : ‘ POST ‘ , URL : ‘ / myApi ‘ , } )

as ( ‘apiCheck’ ) cy

Besuch ( ‘/’ ) cy

warte ( ‘@apiCheck’ )

then ((interception) => {assert

isNotNull (interception

response

body, ‘1st API call has data’) }) cy

warte ( ‘@apiCheck’ )

then ((interception) => {assert

isNotNull (interception

response

body, ‘2nd API call has data’) }) cy

warte ( ‘@apiCheck’ )

then ( (interception) => {assert

isNotNull (interception

response

body, ‘3rd API call has data’) })

Das Warten auf einer Alias-Route hat große Vorteile:

Tests sind robuster mit viel weniger Flake

Fehlermeldungen sind viel präziser

Sie können Aussagen über das zugrunde liegende Anforderungsobjekt machen

Lassen Sie uns jeden Vorteil untersuchen

Flake

Ein Vorteil des deklarativen Wartens auf Antworten besteht darin, dass es Testflocken verringert

Sie können sich cy.wait() als einen Wächter vorstellen, der Cypress anzeigt, wenn Sie erwarten, dass eine Anfrage gestellt wird, die einem bestimmten Routing-Alias ​​entspricht

Dies verhindert, dass die nächsten Befehle ausgeführt werden, bis Antworten zurückkommen, und es schützt vor Situationen, in denen Ihre Anfragen anfänglich verzögert werden

Beispiel für die automatische Vervollständigung:

Was dieses Beispiel unten so leistungsfähig macht, ist, dass Cypress automatisch auf eine Anfrage wartet, die mit dem getSearch-Alias ​​übereinstimmt

Anstatt Cypress zu zwingen, die Nebenwirkung einer erfolgreichen Anfrage (die Anzeige der Buchergebnisse) zu testen, können Sie die eigentliche Ursache der Ergebnisse testen.

cy

abfangen ( ‘/search*’ , [ { item : ‘Book 1’ } , { item : ‘Book 2’ } ] )

as ( ‘getSearch’ ) cy

erhalten ( ‘#autocomplete’ )

Typ ( ‘Buch’ ) cy

warte ( ‘@getSearch’ ) cy

Ergebnisse bekommen’ )

sollte (‘enthalten’ , ‘Buch 1’ )

und ( ‘enthalten’ , ‘Buch 2’ )

Fehler In unserem obigen Beispiel haben wir der Anzeige der Suchergebnisse eine Assertion hinzugefügt

Die Suchergebnisse sind an einige Dinge in unserer Anwendung gekoppelt:

Unsere Anwendung stellt eine Anfrage an die richtige URL

Unsere Anwendung verarbeitet die Antwort korrekt

Unsere Anwendung fügt die Ergebnisse in das DOM ein

In diesem Beispiel gibt es viele mögliche Fehlerquellen

In den meisten Testwerkzeugen würden wir normalerweise immer nur dann eine Fehlermeldung erhalten, wenn wir versuchen, die Ergebnisse im DOM zu finden und sehen, dass es kein passendes Element gibt, wenn unsere Anfrage nicht gesendet wird

Dies ist problematisch, da nicht bekannt ist, warum die Ergebnisse nicht angezeigt werden konnten

Was ist ein Problem mit unserem Rendering-Code? Haben wir ein Attribut wie eine ID oder Klasse eines Elements modifiziert oder geändert? Vielleicht hat uns unser Server verschiedene Buchelemente geschickt

Mit Cypress können Sie Ihr spezifisches Problem leichter lokalisieren, indem Sie ein cy.wait() hinzufügen

Wenn die Antwort nie zurückkam, erhalten Sie eine Fehlermeldung wie diese:

See also  Top agg haftpflichtversicherung New

Jetzt wissen wir genau, warum unser Test fehlgeschlagen ist

Es hatte nichts mit dem DOM zu tun

Stattdessen können wir sehen, dass unsere Anfrage entweder nie gesendet wurde oder dass eine Anfrage an die falsche URL gesendet wurde

Behauptungen

Ein weiterer Vorteil der Verwendung von cy.wait() bei Anfragen besteht darin, dass Sie damit auf das eigentliche Anfrageobjekt zugreifen können

Dies ist nützlich, wenn Sie Zusicherungen zu diesem Objekt machen möchten

In unserem Beispiel oben können wir zu dem Anforderungsobjekt Zusicherungen machen, um zu überprüfen, ob es Daten als Abfragezeichenfolge in der URL gesendet hat

Obwohl wir uns über die Antwort lustig machen, können wir immer noch überprüfen, ob unsere Anwendung die richtige Anfrage sendet.

cy

abfangen ( ‘/search/*’ , [ { item : ‘Book 1’ } , { item : ‘Book 2’ } ] )

as ( ‘getSearch’ ) cy

erhalten ( ‘#autocomplete’ )

Typ ( ‘Buch’ ) cy

warte ( ‘@getSearch’ )

seine ( ‘request.url’ )

sollte ( ‘include’ , ‘/search?query=Book’ ) cy

Ergebnisse bekommen’ )

sollte (‘enthalten’ , ‘Buch 1’ )

und ( ‘enthalten’ , ‘Buch 2’ )

Das Abfangobjekt, das Ihnen cy.wait() liefert, hat alles, was Sie brauchen, um Behauptungen aufzustellen, einschließlich:

URL

Methode

Statuscode

Körper anfordern

Header anfordern

Antworttext

Antwort-Header

Beispiele

cy

abfangen ( ‘POST’ , ‘/users’ )

as ( ‘neuer-benutzer’ ) cy

warte ( ‘@new-user’ )

sollte ( ‘have.property’ , ‘response.statusCode’ , 201 ) cy

get ( ‘@new-user’ )

seine ( ‘request.body’ )

should ( ‘deep.equal’ , JSON

stringify ( { id : ‘101’ , firstName : ‘Joe’ , lastName : ‘Black’ , } ) ) cy

get ( ‘@new-user’ )

sollte ( ( { Anfrage , Antwort } ) => { erwarten ( Anfrage

URL )

bis

übereinstimmen ( / \/ Benutzer $ / ) erwarten ( Anfrage

Methode )

bis

gleich ( ‘POST’ ) erwarten ( Antwort

Header , ‘response headers’ ). to. include ( { ‘cache-control’ : ‘no-cache’ , expires : ‘-1’ , ‘content-type’ : ‘application/json; charset=utf-8’ , location : ‘/users/101′ , } ) } )

Tipp: Sie können das vollständige Anforderungszyklusobjekt überprüfen, indem Sie es in der Konsole protokollieren

cy

warte ( ‘@new-user’ )

dann ( Konsole

log )

Befehlsprotokoll

Cypress protokolliert alle XMLHttpRequest s und ruft sie von der zu testenden Anwendung im Befehlsprotokoll ab

Hier ist ein Beispiel dafür, wie das aussieht:

Der kreisförmige Indikator auf der linken Seite zeigt an, ob die Anfrage an den Zielserver gegangen ist oder nicht

Wenn der Kreis ausgefüllt ist, ging die Anfrage an den Zielserver; Wenn es umrissen ist, wurde die Antwort von cy.intercept() oder cy.route() gestubbt und nicht nach außen gesendet

Wenn wir unseren vorherigen Test erneut ausführen, um dieselben Anforderungen zu stellen, fügen Sie diesmal jedoch ein cy.intercept hinzu () um die Antwort auf /users abzubrechen, können wir sehen, dass sich der Indikator ändert

Nach dem Hinzufügen der folgenden Zeile:

cy

abfangen ( ‘/users*’ , [ ‘user1’ , ‘user2’ ] )

als ( ‘getUsers’ )

Das Befehlsprotokoll sieht folgendermaßen aus:

Die Abrufanforderung hat jetzt einen offenen Kreis, um anzuzeigen, dass sie gestubbt wurde

Beachten Sie auch, dass der Alias ​​für cy.intercept() jetzt auf der rechten Seite des Befehlsprotokolls angezeigt wird

Wenn Sie mit der Maus über den Alias ​​fahren, können Sie weitere Informationen darüber sehen, wie die Anfrage bearbeitet wurde:

Außerdem wird die Anfrage gekennzeichnet, wenn die Anfrage und/oder Antwort von einer cy.intercept()-Handlerfunktion geändert wurde

Wenn wir diesen Code hinzufügen, um ausgehende Anfragen an /users zu ändern:

cy

intercept ( ‘/users*’ , ( req ) => { req

headers [ ‘authorization’ ] = ‘bearer my-bearer-auth-token’ } )

als (‘addAuthHeader’ )

Das Anforderungsprotokoll für /users gibt an, dass das req-Objekt geändert wurde, die Anforderung jedoch noch vom Ziel erfüllt wurde (gefüllter Indikator):

Wie Sie sehen können, wird im Badge „Req Modified“ angezeigt, um anzuzeigen, dass das Anforderungsobjekt geändert wurde

„Res Modified“ und „Req + Res Modified“ können ebenfalls angezeigt werden, je nachdem, ob Res innerhalb eines req.continue()-Callbacks geändert wurde

Wie bei allen Befehlsprotokollen können Protokolle für Netzwerkanfragen angeklickt werden, um zusätzliche Informationen anzuzeigen in der Konsole

Nachdem wir beispielsweise auf die vorherige Anfrage für /users?limit=100 geklickt und die Entwicklertools geöffnet haben, können wir Folgendes sehen:

Also siehe

Economie Academy : les speltheorie (concept: Samenwerken en onderhandelen) Update New

Video ansehen

Neues Update zum Thema concept strategie

concept strategie Sie können die schönen Bilder im Thema sehen

 Update  Economie Academy : les speltheorie (concept: Samenwerken en onderhandelen)
Economie Academy : les speltheorie (concept: Samenwerken en onderhandelen) New

HTC Advies – Horeca & Catering | Foodservice & Hospitality … Aktualisiert

HTC Advies ontwikkelt samen met opdrachtgevers hospitality concepten die inspireren én rendement opleveren. Dat doen we ondernemend en deskundig.

+ hier mehr lesen

Read more

Eten en drinken is omgeven met wooonten en delen we met other

In ons dagelijks leven, maar auch rondom een ​​ingrijpendent moment than de dood.

De Blue Ocean Marketing Strategie uitgelegd Update

Video unten ansehen

Neues Update zum Thema concept strategie

concept strategie Sie können die schönen Bilder im Thema sehen

 Update  De Blue Ocean Marketing Strategie uitgelegd
De Blue Ocean Marketing Strategie uitgelegd Update

Sie können weitere Informationen zum Thema anzeigen concept strategie

Updating

Suche zum Thema concept strategie

Updating

Ende des Themas concept strategie

Articles compiled by Msi-thailand.com. See more articles in category: Blog

Leave a Comment