├── .eslintrc.json ├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json └── test └── e2e ├── components ├── Form.js ├── Header.js └── Preview.js ├── page-objects └── CreateImage.js ├── protractor.conf.js └── specs └── createImage.spec.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true, 5 | "browser": true, 6 | "jasmine": true, 7 | "protractor": true 8 | }, 9 | "extends": "eslint:recommended", 10 | "parserOptions": { 11 | "sourceType": "module" 12 | }, 13 | "rules": { 14 | "arrow-body-style": [ 15 | "error", 16 | "as-needed" 17 | ], 18 | "arrow-parens": [ 19 | "error", 20 | "as-needed" 21 | ], 22 | "indent": [ 23 | "error", 24 | 2 25 | ], 26 | "linebreak-style": [ 27 | "error", 28 | "unix" 29 | ], 30 | "quotes": [ 31 | "error", 32 | "double" 33 | ], 34 | "semi": [ 35 | "error", 36 | "always" 37 | ], 38 | "no-var": 2, 39 | "one-var": 0, 40 | "prefer-const": 2, 41 | "prefer-arrow-callback": 2 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Walmyr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Protractor Components and Page Objects 2 | 3 | This sample project intends to demonstrate an architecture proposal for writing graphical user interface (GUI) tests with [Protractor](http://www.protractortest.org/#/) using a concept of Page Objects composed by Components. 4 | 5 | ## The inspiration 6 | 7 | In October, 2017 I went to Berlin for the SeleniumConf and I watched a presentation by Archit Pal Singh Sachdeva, Software Engineer at Facebook, about [readable, stable and maintainable E2E testing](https://www.seleniumconf.de/talks#archit-pal-singh-sachdeva), and this presentation made me **re-think** on how GUI E2E tests are written, where the main solution for code organization and maintainability is usually the use of the [Page Objects](https://github.com/SeleniumHQ/selenium/wiki/PageObjects) pattern. 8 | But what about using Page Objects together with Components? 9 | 10 | ## A hypothetical example 11 | 12 | I think examples are the better way to explain how code works, so I'll explain you this concept using a hypothetical example of a web application where you can create images, giving each image a name, a description, and a URL pointing to such image in the web. 13 | 14 | The page that we will work in this example would look like this: 15 | 16 | ``` 17 | ------------------------------------------------------ 18 | | Create image | 19 | ------------------------------------------------------ 20 | | | | 21 | | | Preview | 22 | | Name: [ ] | --------- | 23 | | Description: [ ] | | | | 24 | | Image URL: [ ] | | \o/ | | 25 | | | | | | 26 | | | --------- | 27 | | | | 28 | | [Cancel] [Submit] | | 29 | ------------------------------------------------------- 30 | ``` 31 | 32 | Imagine that this page is composed by three main components, the header component, the form component, and the preview component. 33 | The header component contains one element, which is a heading with the text 'Create image'. That's it. 34 | The form component contains five elements, three text input fields (Name, Description, and Image URL), and two buttons (Cancel and Submit). 35 | And the preview component contains two elements, a title (Preview), which is a heading, and a preview image. 36 | 37 | Now let's see how we would structure our `CreateImage` Page Object so that it could be composed by these three different Components. 38 | 39 | ### Page object definition 40 | 41 | A Page Object is defined by a relative URL, and one or more components. In this case, the `CreateImage` Page Object would look like this: 42 | 43 | ```js 44 | // test/e2e/page-objects/CreateImage.js 45 | 46 | const FormComponent = require("../components/Form"); 47 | const HeaderComponent = require("../components/Header"); 48 | const PreviewComponent = require("../components/Preview"); 49 | 50 | class CreateImage { 51 | constructor() { 52 | this._relativeUrl = "/create-image"; 53 | 54 | this.header = new HeaderComponent(); 55 | this.form = new FormComponent(); 56 | this.preview = new PreviewComponent(); 57 | } 58 | 59 | get relativeUrl() { 60 | return this._relativeUrl; 61 | } 62 | } 63 | 64 | module.exports = CreateImage; 65 | ``` 66 | 67 | Note that it starts requiring the `FormComponent`, the `HeaderComponent` and the `PreviewComponent` in the beginning, and the class itself has only four attributes in the constructor, a `_relativeUrl` with a string as its value (`"/create-image"`), a `header`, as an instance of the `HeaderComponent`, a `form`, as an instance of the `FormComponent`, and a `preview`, as an instance of the `PreviewComponent`. 68 | 69 | > Notice that the relative URL is prefixed with a underscore (`_`). In JavaScript, this means that such attribute should not be direclty accessed. To access it we need to use its `get` method, which is defined right after the constructor (`get relativeUrl()`). 70 | 71 | As you can see, the page object has no definition of web elements, it just instantiates the components that compose it, which makes the code simpler and separates better the responsibilities. 72 | 73 | ### Form component definition 74 | 75 | Let's examine the `FormComponent`. 76 | 77 | ```js 78 | // test/e2e/components/Form.js 79 | 80 | const helper = require("protractor-helper"); 81 | 82 | class Form { 83 | constructor() { 84 | this._parentElement = element(by.css("form")); 85 | 86 | this._nameField = this._parentElement.element(by.css(".fields #name")); 87 | this._descriptionField = this._parentElement.element( 88 | by.css(".fields #description") 89 | ); 90 | this._imageUrlField = this._parentElement.element(by.css(".fields #image-url")); 91 | this._cancelButton = this._parentElement.element( 92 | by.css(".actions .cancel-button") 93 | ); 94 | this._submitButton = this._parentElement.element( 95 | by.css(".actions input[type='submit']") 96 | ); 97 | } 98 | 99 | get nameField() { 100 | return this._nameField; 101 | } 102 | 103 | get descriptionField() { 104 | return this._descriptionField; 105 | } 106 | 107 | get imageUrlField() { 108 | return this._imageUrlField; 109 | } 110 | 111 | get cancelButton() { 112 | return this._cancelButton; 113 | } 114 | 115 | get submitButton() { 116 | return this._submitButton; 117 | } 118 | 119 | fillWithDataAndSubmit(data) { 120 | helper.fillFieldWithText(this.nameField, data.name); 121 | helper.fillFieldWithText(this.descriptionField, data.description); 122 | helper.fillFieldWithText(this.imageUrlField, data.imageUrlValue); 123 | helper.click(this.submitButton); 124 | } 125 | } 126 | 127 | module.exports = Form; 128 | ``` 129 | 130 | First of all, the `Form` component requires an external library ([`protractor-helper`](http://npmjs.com/package/protractor-helper)). This library will be used in the component's method `fillWithDataAndSubmit` to interact with the elements only when they are ready for interaction. 131 | 132 | Then, differently than the Page Object, instead of having as first attribute of the constructor a relative URL, it has a `_parentElement`, which in this case is a `form`. This `_parentElement` is used in the definition of any other elements of this component, and this is done to ensure that the elements are correctly and specifically located, meaning that in the DOM the elements are inside their correct parent element (the `_parentElement`). 133 | 134 | As you can see, all other elements (`_nameField`, `_descriptionField`, `_imageUrlField`, `_cancelButton`, and `_submitButton` are defined based on their parent element (`_parentElement`). 135 | 136 | Then, getters are defined for all the previously mentioned elements (except for the `_parentElement`). 137 | 138 | > This is why all elements are prefixed with an underscore (`_`). This, in JavaScript, means that such attributes should not be direclty accessed, and to access them we need to use their `get` methods. 139 | 140 | And finally, it defines the `fillWithDataAndSubmit` method, that receives a `data` object as an argument, and uses it for filling the form with and submitting it. 141 | 142 | The `fillWithDataAndSubmit` method uses the `helper` defined in the beginning of the file to ensure that it will interact with the elements only when they are ready for it, as previously mentioned. 143 | 144 | > Note that the `fillWithDataAndSubmit` method interacts with the attributes (elements) through their `get` methods, not directly. 145 | 146 | Let's see the `HeaderComponent` then. 147 | 148 | ```js 149 | // test/e2e/components/Header.js 150 | 151 | class Header { 152 | constructor() { 153 | this._parentElement = element(by.css("header")); 154 | 155 | this._heading = this._parentElement.element(by.css("h1")); 156 | } 157 | 158 | get heading() { 159 | return this._heading; 160 | } 161 | } 162 | 163 | module.exports = Header; 164 | ``` 165 | 166 | The `Header` component is a simpler one. As the `Form` component, it also defines a `_parentElement`, for the exact same reason, and then it defines a `_heading` element based on the `_parentElement`, and a `get` method for the `_heading` element. 167 | 168 | And now let's examine the `PreviewComponent`. 169 | 170 | ```js 171 | // test/e2e/components/Preview.js 172 | 173 | class Preview { 174 | constructor() { 175 | this._parentElement = element(by.css(".preview")); 176 | 177 | this._title = this._parentElement.element(by.css("h2")); 178 | this._image = this._parentElement.element(by.css("img")); 179 | } 180 | 181 | get title() { 182 | return this._title; 183 | } 184 | 185 | get image() { 186 | return this._image; 187 | } 188 | } 189 | 190 | module.exports = Preview; 191 | ``` 192 | 193 | The `Preview` component is also a simple one. As the `Form` and the `Header` components, it also defines a `_parentElement`, and then it defines two other elements, `_title`, and `_image`, both based on the `_parentElement`. Also, it defines `get` methods for both `_title` and `_image` elements. 194 | 195 | > By using this practice we give the components the responsibilities of defining the elements and methods, and nothing else. 196 | 197 | ___ 198 | 199 | > Page Objects and Components are exported using `module.exports` to expose their APIs for usage, on tests, for example. 200 | 201 | Now let's see how a test file would look like. 202 | 203 | ### Test definition 204 | 205 | ```js 206 | // test/e2e/specs/createImage.spec.js 207 | 208 | const helper = require("protractor-helper"); 209 | 210 | const CreateImagePage = require("../page-objects/CreateImage"); 211 | 212 | describe("Given I access the relative URL '/create-image'", () => { 213 | const createImagePage = new CreateImagePage(); 214 | 215 | beforeEach(() => browser.get(createImagePage.relativeUrl)); 216 | 217 | describe("Happy path", () => { 218 | describe("When I fill the image URL field with a valid value", () => { 219 | const imageUrlValue = "http://example.com/some-image.png"; 220 | 221 | beforeEach(() => 222 | helper.fillFieldWithText( 223 | createImagePage.form.imageUrlField, 224 | imageUrlValue 225 | ) 226 | ); 227 | 228 | it("Then the image preview element uses the provided value in the 'src' attribute", () => { 229 | expect(createImagePage.preview.image.getAttribute("src")).toEqual( 230 | imageUrlValue 231 | ); 232 | }); 233 | }); 234 | 235 | describe("When I click the header's heading", () => { 236 | beforeEach(() => helper.click(createImagePage.header.heading)); 237 | 238 | it("Then I'm redirected to the home page", () => { 239 | helper.waitForUrlToBeEqualToExpectedUrl(browser.baseUrl); 240 | }); 241 | }); 242 | 243 | describe("When I submit the form with valid data", () => { 244 | let data; 245 | 246 | beforeEach(() => { 247 | data = { 248 | name: "Magic cube", 249 | description: "The nicest toy ever.", 250 | imageUrlValue: "http://example.com/magic-cube.png" 251 | }; 252 | 253 | createImagePage.form.fillWithDataAndSubmit(data); 254 | }); 255 | 256 | it("Then all fields are cleared and a success message is shown", () => { 257 | helper.waitForTextNotToBePresentInElement( 258 | createImagePage.form.nameField, 259 | data.name 260 | ); 261 | helper.waitForTextNotToBePresentInElement( 262 | createImagePage.form.descriptionField, 263 | data.description 264 | ); 265 | helper.waitForTextNotToBePresentInElement( 266 | createImagePage.form.imageUrlField, 267 | data.imageUrlValue 268 | ); 269 | 270 | const successMessage = element(by.css(".success-message")); 271 | 272 | helper.waitForElementVisibility(successMessage); 273 | }); 274 | }); 275 | }); 276 | 277 | describe("Alternate paths", () => { 278 | describe("When I submit the form without filling the name, description, and image URL", () => { 279 | it("Then all required fields are shown in red, meaning error", () => { 280 | helper.click(createImagePage.form.submitButton); 281 | 282 | expect( 283 | createImagePage.form.nameField.getCssValue("background-color") 284 | ).toEqual("rgb(255,0,0)"); 285 | expect( 286 | createImagePage.form.descriptionField.getCssValue("background-color") 287 | ).toEqual("rgb(255,0,0)"); 288 | expect( 289 | createImagePage.form.imageUrlField.getCssValue("background-color") 290 | ).toEqual("rgb(255,0,0)"); 291 | }); 292 | }); 293 | 294 | describe("When I submit the form with a name and description, but a missing image URL", () => { 295 | beforeEach(() => { 296 | const dataSetWithMissingImageUrl = { 297 | name: "Boo", 298 | description: "The nicest kid! From Monters Inc.", 299 | imageUrlValue: "" 300 | }; 301 | 302 | createImagePage.form.fillWithDataAndSubmit(dataSetWithMissingImageUrl); 303 | }); 304 | 305 | it("Then the required field (image URL) is shown in red, meaning error", () => { 306 | expect( 307 | createImagePage.form.imageUrlField.getCssValue("background-color") 308 | ).toEqual("rgb(255,0,0)"); 309 | }); 310 | }); 311 | }); 312 | }); 313 | ``` 314 | 315 | In the test file it's worth paying attention to some things. 316 | 317 | - The tests are written using the keywords **Given**, **When**, and **Then**. This helps on understanding the pre-requirements of each test case, what are the actions performed, and what are the expected conditions. 318 | - Only the page object is required at the top of the file. There is no need to require the components since they are already available through the Page Object. 319 | - When running the `browser.get()` in the `beforeEach` statement we pass the `relativeUrl` of the `createImagePage` as an argument (this will be concatenated with the `baseUrl` defined in the `protractor.conf.js` file). If the base URL changes, we just need to update it in a single place, which is the configuration file. 320 | - When running the test's **actions** and **assertions** (from [arrange, **act**, **assert**](http://wiki.c2.com/?ArrangeActAssert)), the following structure is used: 321 | 322 | ```js 323 | // 1st test 324 | // Assert 325 | expect(createImagePage.preview.image.getAttribute("src")).toEqual(imageUrlValue); 326 | 327 | // 2nd test 328 | // Act 329 | beforeEach(() => helper.click(createImagePage.header.heading)); 330 | 331 | // 3rd test 332 | // Assert 333 | helper.waitForTextNotToBePresentInElement(createImagePage.form.nameField, data.name); 334 | helper.waitForTextNotToBePresentInElement(createImagePage.form.descriptionField, data.description); 335 | helper.waitForTextNotToBePresentInElement(createImagePage.form.imageUrlField, data.imageUrlValue); 336 | 337 | // 4th test 338 | // Act 339 | helper.click(createImagePage.form.submitButton); 340 | // Assert 341 | expect(createImagePage.form.nameField.getCssValue("background-color")).toEqual("rgb(255,0,0)"); 342 | expect(createImagePage.form.descriptionField.getCssValue("background-color")).toEqual("rgb(255,0,0)"); 343 | expect(createImagePage.form.imageUrlField.getCssValue("background-color")).toEqual("rgb(255,0,0)"); 344 | 345 | // 5th test 346 | // Act 347 | createImagePage.form.fillWithDataAndSubmit(dataSetWithMissingImageUrl); 348 | // Assert 349 | expect(createImagePage.form.imageUrlField.getCssValue("background-color")).toEqual("rgb(255,0,0)"); 350 | ``` 351 | 352 | Note how easy it becames to access the components, and its elements and method(s) from the Page Object. 353 | 354 | Another example of an expectation, or **assertion**, could be something like this: 355 | 356 | ```js 357 | expect(createImagePage.preview.title.getText()).toEqual("Preview"); 358 | ``` 359 | 360 | This expectation tells Protractor the following: get the text of the `title` element that is contained in the `preview` Component of the `createImagePage` Page Object, and check if it is equal to a certain text (`"Preview"`). 361 | 362 | > Note that the `protractor-helper` library is not used in the above example. 363 | 364 | Another example of expectation, now using the `protractor-helper` library would look like this: 365 | 366 | ```js 367 | helper.waitForTextToBePresentInElement(createImagePage.preview.title, "Preview"); 368 | ``` 369 | 370 | Differently from the previous expectation, this one tells Protractor the following: wait for the text `"Preview"` to be present in the `title` element of the `preview` component, of the `createImagePage` Page Object. 371 | 372 | > This is more like an implicit expectation since there is no `expect` keyword on it, but if the text is not present in the element after the default timeout (which by default is 5000 milliseconds), the test would still fail, meaning that it can still be used as an expectation. 373 | 374 | ## Conclusion 375 | 376 | By writing tests using not only Page Objects but also the concept of Components, we can benefit from: 377 | - Having smaller classes that are easier to read and maintain. 378 | - We separate responsibilities, where Page Objects have only a relative URL and instances of the Components they are composed by, while Components define elements and methods. 379 | - We have better defined elements, because we use the `_parentElement` when defining the children elements that will be used in the tests, making sure we will interact with the correct elements in cases of elements in the DOM with part of the same CSS selector, but in different parts of the application. 380 | - We have more reliable test cases, because we define elements in a smarter way, but also because we use the `protractor-helper` library to interact with elements only when they are ready for interaction. 381 | - Different Page Objects can share already existing Components without the need for code duplication. 382 | - And in case we need we can even work with parent and child components, or with generic (or common) components, wherein the first case the parent component pass its `_parentElement` to the constructor of the child component, and wherein the second case the components that share common elements can use JavaScript inheritance (but these cases are not examplified here). 383 | 384 | ___ 385 | 386 | **Note: If you try to run the tests in this project they will all fail since the application under test doesn't really exist. This project was created only to explain the concepts of writing GUI E2E tests with Protractor using the concept of Page Objects and Components.** 387 | 388 | ___ 389 | 390 | Made with 💚 by [Walmyr Filho](https://walmyr.dev) 391 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protractor-components-and-page-objects", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/q": { 8 | "version": "0.0.32", 9 | "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", 10 | "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", 11 | "dev": true 12 | }, 13 | "@types/selenium-webdriver": { 14 | "version": "3.0.17", 15 | "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.17.tgz", 16 | "integrity": "sha512-tGomyEuzSC1H28y2zlW6XPCaDaXFaD6soTdb4GNdmte2qfHtrKqhy0ZFs4r/1hpazCfEZqeTSRLvSasmEx89uw==", 17 | "dev": true 18 | }, 19 | "acorn": { 20 | "version": "5.7.4", 21 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", 22 | "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", 23 | "dev": true 24 | }, 25 | "acorn-jsx": { 26 | "version": "3.0.1", 27 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 28 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 29 | "dev": true, 30 | "requires": { 31 | "acorn": "^3.0.4" 32 | }, 33 | "dependencies": { 34 | "acorn": { 35 | "version": "3.3.0", 36 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 37 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 38 | "dev": true 39 | } 40 | } 41 | }, 42 | "adm-zip": { 43 | "version": "0.4.14", 44 | "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz", 45 | "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==", 46 | "dev": true 47 | }, 48 | "agent-base": { 49 | "version": "4.3.0", 50 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", 51 | "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", 52 | "dev": true, 53 | "requires": { 54 | "es6-promisify": "^5.0.0" 55 | } 56 | }, 57 | "ajv": { 58 | "version": "5.5.2", 59 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 60 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 61 | "dev": true, 62 | "requires": { 63 | "co": "^4.6.0", 64 | "fast-deep-equal": "^1.0.0", 65 | "fast-json-stable-stringify": "^2.0.0", 66 | "json-schema-traverse": "^0.3.0" 67 | } 68 | }, 69 | "ajv-keywords": { 70 | "version": "2.1.1", 71 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", 72 | "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", 73 | "dev": true 74 | }, 75 | "ansi-escapes": { 76 | "version": "3.2.0", 77 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 78 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", 79 | "dev": true 80 | }, 81 | "ansi-regex": { 82 | "version": "2.1.1", 83 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 84 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 85 | "dev": true 86 | }, 87 | "ansi-styles": { 88 | "version": "2.2.1", 89 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 90 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 91 | "dev": true 92 | }, 93 | "argparse": { 94 | "version": "1.0.10", 95 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 96 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 97 | "dev": true, 98 | "requires": { 99 | "sprintf-js": "~1.0.2" 100 | } 101 | }, 102 | "array-union": { 103 | "version": "1.0.2", 104 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 105 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 106 | "dev": true, 107 | "requires": { 108 | "array-uniq": "^1.0.1" 109 | } 110 | }, 111 | "array-uniq": { 112 | "version": "1.0.3", 113 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 114 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 115 | "dev": true 116 | }, 117 | "arrify": { 118 | "version": "1.0.1", 119 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 120 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 121 | "dev": true 122 | }, 123 | "asn1": { 124 | "version": "0.2.4", 125 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 126 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 127 | "dev": true, 128 | "requires": { 129 | "safer-buffer": "~2.1.0" 130 | } 131 | }, 132 | "assert-plus": { 133 | "version": "1.0.0", 134 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 135 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 136 | "dev": true 137 | }, 138 | "asynckit": { 139 | "version": "0.4.0", 140 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 141 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 142 | "dev": true 143 | }, 144 | "aws-sign2": { 145 | "version": "0.7.0", 146 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 147 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 148 | "dev": true 149 | }, 150 | "aws4": { 151 | "version": "1.9.1", 152 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", 153 | "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", 154 | "dev": true 155 | }, 156 | "babel-code-frame": { 157 | "version": "6.26.0", 158 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 159 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 160 | "dev": true, 161 | "requires": { 162 | "chalk": "^1.1.3", 163 | "esutils": "^2.0.2", 164 | "js-tokens": "^3.0.2" 165 | }, 166 | "dependencies": { 167 | "chalk": { 168 | "version": "1.1.3", 169 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 170 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 171 | "dev": true, 172 | "requires": { 173 | "ansi-styles": "^2.2.1", 174 | "escape-string-regexp": "^1.0.2", 175 | "has-ansi": "^2.0.0", 176 | "strip-ansi": "^3.0.0", 177 | "supports-color": "^2.0.0" 178 | } 179 | }, 180 | "strip-ansi": { 181 | "version": "3.0.1", 182 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 183 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 184 | "dev": true, 185 | "requires": { 186 | "ansi-regex": "^2.0.0" 187 | } 188 | } 189 | } 190 | }, 191 | "balanced-match": { 192 | "version": "1.0.0", 193 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 194 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 195 | "dev": true 196 | }, 197 | "bcrypt-pbkdf": { 198 | "version": "1.0.2", 199 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 200 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 201 | "dev": true, 202 | "requires": { 203 | "tweetnacl": "^0.14.3" 204 | } 205 | }, 206 | "blocking-proxy": { 207 | "version": "1.0.1", 208 | "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", 209 | "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", 210 | "dev": true, 211 | "requires": { 212 | "minimist": "^1.2.0" 213 | } 214 | }, 215 | "brace-expansion": { 216 | "version": "1.1.11", 217 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 218 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 219 | "dev": true, 220 | "requires": { 221 | "balanced-match": "^1.0.0", 222 | "concat-map": "0.0.1" 223 | } 224 | }, 225 | "browserstack": { 226 | "version": "1.6.0", 227 | "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.0.tgz", 228 | "integrity": "sha512-HJDJ0TSlmkwnt9RZ+v5gFpa1XZTBYTj0ywvLwJ3241J7vMw2jAsGNVhKHtmCOyg+VxeLZyaibO9UL71AsUeDIw==", 229 | "dev": true, 230 | "requires": { 231 | "https-proxy-agent": "^2.2.1" 232 | } 233 | }, 234 | "buffer-from": { 235 | "version": "1.1.1", 236 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 237 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 238 | "dev": true 239 | }, 240 | "caller-path": { 241 | "version": "0.1.0", 242 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 243 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 244 | "dev": true, 245 | "requires": { 246 | "callsites": "^0.2.0" 247 | } 248 | }, 249 | "callsites": { 250 | "version": "0.2.0", 251 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 252 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 253 | "dev": true 254 | }, 255 | "caseless": { 256 | "version": "0.12.0", 257 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 258 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 259 | "dev": true 260 | }, 261 | "chalk": { 262 | "version": "2.4.2", 263 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 264 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 265 | "dev": true, 266 | "requires": { 267 | "ansi-styles": "^3.2.1", 268 | "escape-string-regexp": "^1.0.5", 269 | "supports-color": "^5.3.0" 270 | }, 271 | "dependencies": { 272 | "ansi-styles": { 273 | "version": "3.2.1", 274 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 275 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 276 | "dev": true, 277 | "requires": { 278 | "color-convert": "^1.9.0" 279 | } 280 | }, 281 | "supports-color": { 282 | "version": "5.5.0", 283 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 284 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 285 | "dev": true, 286 | "requires": { 287 | "has-flag": "^3.0.0" 288 | } 289 | } 290 | } 291 | }, 292 | "chardet": { 293 | "version": "0.4.2", 294 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 295 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", 296 | "dev": true 297 | }, 298 | "circular-json": { 299 | "version": "0.3.3", 300 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", 301 | "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", 302 | "dev": true 303 | }, 304 | "cli-cursor": { 305 | "version": "2.1.0", 306 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 307 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 308 | "dev": true, 309 | "requires": { 310 | "restore-cursor": "^2.0.0" 311 | } 312 | }, 313 | "cli-width": { 314 | "version": "2.2.1", 315 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", 316 | "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", 317 | "dev": true 318 | }, 319 | "co": { 320 | "version": "4.6.0", 321 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 322 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 323 | "dev": true 324 | }, 325 | "color-convert": { 326 | "version": "1.9.3", 327 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 328 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 329 | "dev": true, 330 | "requires": { 331 | "color-name": "1.1.3" 332 | } 333 | }, 334 | "color-name": { 335 | "version": "1.1.3", 336 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 337 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 338 | "dev": true 339 | }, 340 | "colors": { 341 | "version": "1.1.2", 342 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", 343 | "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", 344 | "dev": true 345 | }, 346 | "combined-stream": { 347 | "version": "1.0.8", 348 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 349 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 350 | "dev": true, 351 | "requires": { 352 | "delayed-stream": "~1.0.0" 353 | } 354 | }, 355 | "concat-map": { 356 | "version": "0.0.1", 357 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 358 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 359 | "dev": true 360 | }, 361 | "concat-stream": { 362 | "version": "1.6.2", 363 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 364 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 365 | "dev": true, 366 | "requires": { 367 | "buffer-from": "^1.0.0", 368 | "inherits": "^2.0.3", 369 | "readable-stream": "^2.2.2", 370 | "typedarray": "^0.0.6" 371 | } 372 | }, 373 | "core-util-is": { 374 | "version": "1.0.2", 375 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 376 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 377 | "dev": true 378 | }, 379 | "cross-spawn": { 380 | "version": "5.1.0", 381 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 382 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 383 | "dev": true, 384 | "requires": { 385 | "lru-cache": "^4.0.1", 386 | "shebang-command": "^1.2.0", 387 | "which": "^1.2.9" 388 | } 389 | }, 390 | "dashdash": { 391 | "version": "1.14.1", 392 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 393 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 394 | "dev": true, 395 | "requires": { 396 | "assert-plus": "^1.0.0" 397 | } 398 | }, 399 | "debug": { 400 | "version": "3.2.6", 401 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 402 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 403 | "dev": true, 404 | "requires": { 405 | "ms": "^2.1.1" 406 | } 407 | }, 408 | "deep-is": { 409 | "version": "0.1.3", 410 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 411 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 412 | "dev": true 413 | }, 414 | "del": { 415 | "version": "2.2.2", 416 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 417 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 418 | "dev": true, 419 | "requires": { 420 | "globby": "^5.0.0", 421 | "is-path-cwd": "^1.0.0", 422 | "is-path-in-cwd": "^1.0.0", 423 | "object-assign": "^4.0.1", 424 | "pify": "^2.0.0", 425 | "pinkie-promise": "^2.0.0", 426 | "rimraf": "^2.2.8" 427 | } 428 | }, 429 | "delayed-stream": { 430 | "version": "1.0.0", 431 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 432 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 433 | "dev": true 434 | }, 435 | "doctrine": { 436 | "version": "2.1.0", 437 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 438 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 439 | "dev": true, 440 | "requires": { 441 | "esutils": "^2.0.2" 442 | } 443 | }, 444 | "ecc-jsbn": { 445 | "version": "0.1.2", 446 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 447 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 448 | "dev": true, 449 | "requires": { 450 | "jsbn": "~0.1.0", 451 | "safer-buffer": "^2.1.0" 452 | } 453 | }, 454 | "es6-promise": { 455 | "version": "4.2.8", 456 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", 457 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", 458 | "dev": true 459 | }, 460 | "es6-promisify": { 461 | "version": "5.0.0", 462 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", 463 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", 464 | "dev": true, 465 | "requires": { 466 | "es6-promise": "^4.0.3" 467 | } 468 | }, 469 | "escape-string-regexp": { 470 | "version": "1.0.5", 471 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 472 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 473 | "dev": true 474 | }, 475 | "eslint": { 476 | "version": "4.19.1", 477 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", 478 | "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", 479 | "dev": true, 480 | "requires": { 481 | "ajv": "^5.3.0", 482 | "babel-code-frame": "^6.22.0", 483 | "chalk": "^2.1.0", 484 | "concat-stream": "^1.6.0", 485 | "cross-spawn": "^5.1.0", 486 | "debug": "^3.1.0", 487 | "doctrine": "^2.1.0", 488 | "eslint-scope": "^3.7.1", 489 | "eslint-visitor-keys": "^1.0.0", 490 | "espree": "^3.5.4", 491 | "esquery": "^1.0.0", 492 | "esutils": "^2.0.2", 493 | "file-entry-cache": "^2.0.0", 494 | "functional-red-black-tree": "^1.0.1", 495 | "glob": "^7.1.2", 496 | "globals": "^11.0.1", 497 | "ignore": "^3.3.3", 498 | "imurmurhash": "^0.1.4", 499 | "inquirer": "^3.0.6", 500 | "is-resolvable": "^1.0.0", 501 | "js-yaml": "^3.9.1", 502 | "json-stable-stringify-without-jsonify": "^1.0.1", 503 | "levn": "^0.3.0", 504 | "lodash": "^4.17.4", 505 | "minimatch": "^3.0.2", 506 | "mkdirp": "^0.5.1", 507 | "natural-compare": "^1.4.0", 508 | "optionator": "^0.8.2", 509 | "path-is-inside": "^1.0.2", 510 | "pluralize": "^7.0.0", 511 | "progress": "^2.0.0", 512 | "regexpp": "^1.0.1", 513 | "require-uncached": "^1.0.3", 514 | "semver": "^5.3.0", 515 | "strip-ansi": "^4.0.0", 516 | "strip-json-comments": "~2.0.1", 517 | "table": "4.0.2", 518 | "text-table": "~0.2.0" 519 | } 520 | }, 521 | "eslint-scope": { 522 | "version": "3.7.3", 523 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", 524 | "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", 525 | "dev": true, 526 | "requires": { 527 | "esrecurse": "^4.1.0", 528 | "estraverse": "^4.1.1" 529 | } 530 | }, 531 | "eslint-visitor-keys": { 532 | "version": "1.1.0", 533 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 534 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 535 | "dev": true 536 | }, 537 | "espree": { 538 | "version": "3.5.4", 539 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", 540 | "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", 541 | "dev": true, 542 | "requires": { 543 | "acorn": "^5.5.0", 544 | "acorn-jsx": "^3.0.0" 545 | } 546 | }, 547 | "esprima": { 548 | "version": "4.0.1", 549 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 550 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 551 | "dev": true 552 | }, 553 | "esquery": { 554 | "version": "1.3.0", 555 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.0.tgz", 556 | "integrity": "sha512-/5qB+Mb0m2bh86tjGbA8pB0qBfdmCIK6ZNPjcw4/TtEH0+tTf0wLA5HK4KMTweSMwLGHwBDWCBV+6+2+EuHmgg==", 557 | "dev": true, 558 | "requires": { 559 | "estraverse": "^5.0.0" 560 | }, 561 | "dependencies": { 562 | "estraverse": { 563 | "version": "5.0.0", 564 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", 565 | "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", 566 | "dev": true 567 | } 568 | } 569 | }, 570 | "esrecurse": { 571 | "version": "4.2.1", 572 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 573 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 574 | "dev": true, 575 | "requires": { 576 | "estraverse": "^4.1.0" 577 | } 578 | }, 579 | "estraverse": { 580 | "version": "4.3.0", 581 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 582 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 583 | "dev": true 584 | }, 585 | "esutils": { 586 | "version": "2.0.3", 587 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 588 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 589 | "dev": true 590 | }, 591 | "exit": { 592 | "version": "0.1.2", 593 | "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", 594 | "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", 595 | "dev": true 596 | }, 597 | "extend": { 598 | "version": "3.0.2", 599 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 600 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 601 | "dev": true 602 | }, 603 | "external-editor": { 604 | "version": "2.2.0", 605 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 606 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 607 | "dev": true, 608 | "requires": { 609 | "chardet": "^0.4.0", 610 | "iconv-lite": "^0.4.17", 611 | "tmp": "^0.0.33" 612 | } 613 | }, 614 | "extsprintf": { 615 | "version": "1.3.0", 616 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 617 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 618 | "dev": true 619 | }, 620 | "fast-deep-equal": { 621 | "version": "1.1.0", 622 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 623 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", 624 | "dev": true 625 | }, 626 | "fast-json-stable-stringify": { 627 | "version": "2.1.0", 628 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 629 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 630 | "dev": true 631 | }, 632 | "fast-levenshtein": { 633 | "version": "2.0.6", 634 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 635 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 636 | "dev": true 637 | }, 638 | "figures": { 639 | "version": "2.0.0", 640 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 641 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 642 | "dev": true, 643 | "requires": { 644 | "escape-string-regexp": "^1.0.5" 645 | } 646 | }, 647 | "file-entry-cache": { 648 | "version": "2.0.0", 649 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 650 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 651 | "dev": true, 652 | "requires": { 653 | "flat-cache": "^1.2.1", 654 | "object-assign": "^4.0.1" 655 | } 656 | }, 657 | "flat-cache": { 658 | "version": "1.3.4", 659 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", 660 | "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", 661 | "dev": true, 662 | "requires": { 663 | "circular-json": "^0.3.1", 664 | "graceful-fs": "^4.1.2", 665 | "rimraf": "~2.6.2", 666 | "write": "^0.2.1" 667 | } 668 | }, 669 | "forever-agent": { 670 | "version": "0.6.1", 671 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 672 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 673 | "dev": true 674 | }, 675 | "form-data": { 676 | "version": "2.3.3", 677 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 678 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 679 | "dev": true, 680 | "requires": { 681 | "asynckit": "^0.4.0", 682 | "combined-stream": "^1.0.6", 683 | "mime-types": "^2.1.12" 684 | } 685 | }, 686 | "fs.realpath": { 687 | "version": "1.0.0", 688 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 689 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 690 | "dev": true 691 | }, 692 | "functional-red-black-tree": { 693 | "version": "1.0.1", 694 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 695 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 696 | "dev": true 697 | }, 698 | "getpass": { 699 | "version": "0.1.7", 700 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 701 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 702 | "dev": true, 703 | "requires": { 704 | "assert-plus": "^1.0.0" 705 | } 706 | }, 707 | "glob": { 708 | "version": "7.1.6", 709 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 710 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 711 | "dev": true, 712 | "requires": { 713 | "fs.realpath": "^1.0.0", 714 | "inflight": "^1.0.4", 715 | "inherits": "2", 716 | "minimatch": "^3.0.4", 717 | "once": "^1.3.0", 718 | "path-is-absolute": "^1.0.0" 719 | } 720 | }, 721 | "globals": { 722 | "version": "11.12.0", 723 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 724 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 725 | "dev": true 726 | }, 727 | "globby": { 728 | "version": "5.0.0", 729 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 730 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 731 | "dev": true, 732 | "requires": { 733 | "array-union": "^1.0.1", 734 | "arrify": "^1.0.0", 735 | "glob": "^7.0.3", 736 | "object-assign": "^4.0.1", 737 | "pify": "^2.0.0", 738 | "pinkie-promise": "^2.0.0" 739 | } 740 | }, 741 | "graceful-fs": { 742 | "version": "4.2.3", 743 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", 744 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", 745 | "dev": true 746 | }, 747 | "har-schema": { 748 | "version": "2.0.0", 749 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 750 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 751 | "dev": true 752 | }, 753 | "har-validator": { 754 | "version": "5.1.3", 755 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 756 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 757 | "dev": true, 758 | "requires": { 759 | "ajv": "^6.5.5", 760 | "har-schema": "^2.0.0" 761 | }, 762 | "dependencies": { 763 | "ajv": { 764 | "version": "6.12.0", 765 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", 766 | "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", 767 | "dev": true, 768 | "requires": { 769 | "fast-deep-equal": "^3.1.1", 770 | "fast-json-stable-stringify": "^2.0.0", 771 | "json-schema-traverse": "^0.4.1", 772 | "uri-js": "^4.2.2" 773 | } 774 | }, 775 | "fast-deep-equal": { 776 | "version": "3.1.1", 777 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", 778 | "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", 779 | "dev": true 780 | }, 781 | "json-schema-traverse": { 782 | "version": "0.4.1", 783 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 784 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 785 | "dev": true 786 | } 787 | } 788 | }, 789 | "has-ansi": { 790 | "version": "2.0.0", 791 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 792 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 793 | "dev": true, 794 | "requires": { 795 | "ansi-regex": "^2.0.0" 796 | } 797 | }, 798 | "has-flag": { 799 | "version": "3.0.0", 800 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 801 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 802 | "dev": true 803 | }, 804 | "http-signature": { 805 | "version": "1.2.0", 806 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 807 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 808 | "dev": true, 809 | "requires": { 810 | "assert-plus": "^1.0.0", 811 | "jsprim": "^1.2.2", 812 | "sshpk": "^1.7.0" 813 | } 814 | }, 815 | "https-proxy-agent": { 816 | "version": "2.2.4", 817 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", 818 | "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", 819 | "dev": true, 820 | "requires": { 821 | "agent-base": "^4.3.0", 822 | "debug": "^3.1.0" 823 | } 824 | }, 825 | "iconv-lite": { 826 | "version": "0.4.24", 827 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 828 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 829 | "dev": true, 830 | "requires": { 831 | "safer-buffer": ">= 2.1.2 < 3" 832 | } 833 | }, 834 | "ignore": { 835 | "version": "3.3.10", 836 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", 837 | "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", 838 | "dev": true 839 | }, 840 | "immediate": { 841 | "version": "3.0.6", 842 | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", 843 | "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", 844 | "dev": true 845 | }, 846 | "imurmurhash": { 847 | "version": "0.1.4", 848 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 849 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 850 | "dev": true 851 | }, 852 | "inflight": { 853 | "version": "1.0.6", 854 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 855 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 856 | "dev": true, 857 | "requires": { 858 | "once": "^1.3.0", 859 | "wrappy": "1" 860 | } 861 | }, 862 | "inherits": { 863 | "version": "2.0.4", 864 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 865 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 866 | "dev": true 867 | }, 868 | "ini": { 869 | "version": "1.3.7", 870 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", 871 | "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", 872 | "dev": true 873 | }, 874 | "inquirer": { 875 | "version": "3.3.0", 876 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", 877 | "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", 878 | "dev": true, 879 | "requires": { 880 | "ansi-escapes": "^3.0.0", 881 | "chalk": "^2.0.0", 882 | "cli-cursor": "^2.1.0", 883 | "cli-width": "^2.0.0", 884 | "external-editor": "^2.0.4", 885 | "figures": "^2.0.0", 886 | "lodash": "^4.3.0", 887 | "mute-stream": "0.0.7", 888 | "run-async": "^2.2.0", 889 | "rx-lite": "^4.0.8", 890 | "rx-lite-aggregates": "^4.0.8", 891 | "string-width": "^2.1.0", 892 | "strip-ansi": "^4.0.0", 893 | "through": "^2.3.6" 894 | } 895 | }, 896 | "is-fullwidth-code-point": { 897 | "version": "2.0.0", 898 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 899 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 900 | "dev": true 901 | }, 902 | "is-path-cwd": { 903 | "version": "1.0.0", 904 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 905 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", 906 | "dev": true 907 | }, 908 | "is-path-in-cwd": { 909 | "version": "1.0.1", 910 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", 911 | "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", 912 | "dev": true, 913 | "requires": { 914 | "is-path-inside": "^1.0.0" 915 | } 916 | }, 917 | "is-path-inside": { 918 | "version": "1.0.1", 919 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", 920 | "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", 921 | "dev": true, 922 | "requires": { 923 | "path-is-inside": "^1.0.1" 924 | } 925 | }, 926 | "is-promise": { 927 | "version": "2.1.0", 928 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 929 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 930 | "dev": true 931 | }, 932 | "is-resolvable": { 933 | "version": "1.1.0", 934 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", 935 | "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", 936 | "dev": true 937 | }, 938 | "is-typedarray": { 939 | "version": "1.0.0", 940 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 941 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 942 | "dev": true 943 | }, 944 | "isarray": { 945 | "version": "1.0.0", 946 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 947 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 948 | "dev": true 949 | }, 950 | "isexe": { 951 | "version": "2.0.0", 952 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 953 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 954 | "dev": true 955 | }, 956 | "isstream": { 957 | "version": "0.1.2", 958 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 959 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 960 | "dev": true 961 | }, 962 | "jasmine": { 963 | "version": "2.8.0", 964 | "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", 965 | "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", 966 | "dev": true, 967 | "requires": { 968 | "exit": "^0.1.2", 969 | "glob": "^7.0.6", 970 | "jasmine-core": "~2.8.0" 971 | } 972 | }, 973 | "jasmine-core": { 974 | "version": "2.8.0", 975 | "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", 976 | "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", 977 | "dev": true 978 | }, 979 | "jasmine-spec-reporter": { 980 | "version": "4.2.1", 981 | "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", 982 | "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", 983 | "dev": true, 984 | "requires": { 985 | "colors": "1.1.2" 986 | } 987 | }, 988 | "jasminewd2": { 989 | "version": "2.2.0", 990 | "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", 991 | "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", 992 | "dev": true 993 | }, 994 | "js-tokens": { 995 | "version": "3.0.2", 996 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 997 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 998 | "dev": true 999 | }, 1000 | "js-yaml": { 1001 | "version": "3.13.1", 1002 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1003 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1004 | "dev": true, 1005 | "requires": { 1006 | "argparse": "^1.0.7", 1007 | "esprima": "^4.0.0" 1008 | } 1009 | }, 1010 | "jsbn": { 1011 | "version": "0.1.1", 1012 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1013 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 1014 | "dev": true 1015 | }, 1016 | "json-schema": { 1017 | "version": "0.2.3", 1018 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 1019 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 1020 | "dev": true 1021 | }, 1022 | "json-schema-traverse": { 1023 | "version": "0.3.1", 1024 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 1025 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", 1026 | "dev": true 1027 | }, 1028 | "json-stable-stringify-without-jsonify": { 1029 | "version": "1.0.1", 1030 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1031 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1032 | "dev": true 1033 | }, 1034 | "json-stringify-safe": { 1035 | "version": "5.0.1", 1036 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1037 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 1038 | "dev": true 1039 | }, 1040 | "jsprim": { 1041 | "version": "1.4.1", 1042 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 1043 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 1044 | "dev": true, 1045 | "requires": { 1046 | "assert-plus": "1.0.0", 1047 | "extsprintf": "1.3.0", 1048 | "json-schema": "0.2.3", 1049 | "verror": "1.10.0" 1050 | } 1051 | }, 1052 | "jszip": { 1053 | "version": "3.3.0", 1054 | "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.3.0.tgz", 1055 | "integrity": "sha512-EJ9k766htB1ZWnsV5ZMDkKLgA+201r/ouFF8R2OigVjVdcm2rurcBrrdXaeqBJbqnUVMko512PYmlncBKE1Huw==", 1056 | "dev": true, 1057 | "requires": { 1058 | "lie": "~3.3.0", 1059 | "pako": "~1.0.2", 1060 | "readable-stream": "~2.3.6", 1061 | "set-immediate-shim": "~1.0.1" 1062 | } 1063 | }, 1064 | "levn": { 1065 | "version": "0.3.0", 1066 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1067 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1068 | "dev": true, 1069 | "requires": { 1070 | "prelude-ls": "~1.1.2", 1071 | "type-check": "~0.3.2" 1072 | } 1073 | }, 1074 | "lie": { 1075 | "version": "3.3.0", 1076 | "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", 1077 | "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", 1078 | "dev": true, 1079 | "requires": { 1080 | "immediate": "~3.0.5" 1081 | } 1082 | }, 1083 | "lodash": { 1084 | "version": "4.17.21", 1085 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1086 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1087 | "dev": true 1088 | }, 1089 | "lru-cache": { 1090 | "version": "4.1.5", 1091 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 1092 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 1093 | "dev": true, 1094 | "requires": { 1095 | "pseudomap": "^1.0.2", 1096 | "yallist": "^2.1.2" 1097 | } 1098 | }, 1099 | "mime-db": { 1100 | "version": "1.43.0", 1101 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 1102 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", 1103 | "dev": true 1104 | }, 1105 | "mime-types": { 1106 | "version": "2.1.26", 1107 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 1108 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 1109 | "dev": true, 1110 | "requires": { 1111 | "mime-db": "1.43.0" 1112 | } 1113 | }, 1114 | "mimic-fn": { 1115 | "version": "1.2.0", 1116 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 1117 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 1118 | "dev": true 1119 | }, 1120 | "minimatch": { 1121 | "version": "3.0.4", 1122 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1123 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1124 | "dev": true, 1125 | "requires": { 1126 | "brace-expansion": "^1.1.7" 1127 | } 1128 | }, 1129 | "minimist": { 1130 | "version": "1.2.5", 1131 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1132 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1133 | "dev": true 1134 | }, 1135 | "mkdirp": { 1136 | "version": "0.5.5", 1137 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1138 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1139 | "dev": true, 1140 | "requires": { 1141 | "minimist": "^1.2.5" 1142 | } 1143 | }, 1144 | "ms": { 1145 | "version": "2.1.2", 1146 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1147 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1148 | "dev": true 1149 | }, 1150 | "mute-stream": { 1151 | "version": "0.0.7", 1152 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 1153 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 1154 | "dev": true 1155 | }, 1156 | "natural-compare": { 1157 | "version": "1.4.0", 1158 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1159 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1160 | "dev": true 1161 | }, 1162 | "oauth-sign": { 1163 | "version": "0.9.0", 1164 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1165 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1166 | "dev": true 1167 | }, 1168 | "object-assign": { 1169 | "version": "4.1.1", 1170 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1171 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1172 | "dev": true 1173 | }, 1174 | "once": { 1175 | "version": "1.4.0", 1176 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1177 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1178 | "dev": true, 1179 | "requires": { 1180 | "wrappy": "1" 1181 | } 1182 | }, 1183 | "onetime": { 1184 | "version": "2.0.1", 1185 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 1186 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 1187 | "dev": true, 1188 | "requires": { 1189 | "mimic-fn": "^1.0.0" 1190 | } 1191 | }, 1192 | "optimist": { 1193 | "version": "0.6.1", 1194 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 1195 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 1196 | "dev": true, 1197 | "requires": { 1198 | "minimist": "~0.0.1", 1199 | "wordwrap": "~0.0.2" 1200 | }, 1201 | "dependencies": { 1202 | "minimist": { 1203 | "version": "0.0.10", 1204 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 1205 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", 1206 | "dev": true 1207 | } 1208 | } 1209 | }, 1210 | "optionator": { 1211 | "version": "0.8.3", 1212 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 1213 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 1214 | "dev": true, 1215 | "requires": { 1216 | "deep-is": "~0.1.3", 1217 | "fast-levenshtein": "~2.0.6", 1218 | "levn": "~0.3.0", 1219 | "prelude-ls": "~1.1.2", 1220 | "type-check": "~0.3.2", 1221 | "word-wrap": "~1.2.3" 1222 | } 1223 | }, 1224 | "os-tmpdir": { 1225 | "version": "1.0.2", 1226 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1227 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 1228 | "dev": true 1229 | }, 1230 | "pako": { 1231 | "version": "1.0.11", 1232 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 1233 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", 1234 | "dev": true 1235 | }, 1236 | "path-is-absolute": { 1237 | "version": "1.0.1", 1238 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1239 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1240 | "dev": true 1241 | }, 1242 | "path-is-inside": { 1243 | "version": "1.0.2", 1244 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1245 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 1246 | "dev": true 1247 | }, 1248 | "performance-now": { 1249 | "version": "2.1.0", 1250 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1251 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 1252 | "dev": true 1253 | }, 1254 | "pify": { 1255 | "version": "2.3.0", 1256 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1257 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1258 | "dev": true 1259 | }, 1260 | "pinkie": { 1261 | "version": "2.0.4", 1262 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1263 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1264 | "dev": true 1265 | }, 1266 | "pinkie-promise": { 1267 | "version": "2.0.1", 1268 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1269 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1270 | "dev": true, 1271 | "requires": { 1272 | "pinkie": "^2.0.0" 1273 | } 1274 | }, 1275 | "pluralize": { 1276 | "version": "7.0.0", 1277 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", 1278 | "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", 1279 | "dev": true 1280 | }, 1281 | "prelude-ls": { 1282 | "version": "1.1.2", 1283 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1284 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1285 | "dev": true 1286 | }, 1287 | "process-nextick-args": { 1288 | "version": "2.0.1", 1289 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1290 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 1291 | "dev": true 1292 | }, 1293 | "progress": { 1294 | "version": "2.0.3", 1295 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1296 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1297 | "dev": true 1298 | }, 1299 | "protractor": { 1300 | "version": "5.4.3", 1301 | "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.3.tgz", 1302 | "integrity": "sha512-7pMAolv8Ah1yJIqaorDTzACtn3gk7BamVKPTeO5lqIGOrfosjPgXFx/z1dqSI+m5EeZc2GMJHPr5DYlodujDNA==", 1303 | "dev": true, 1304 | "requires": { 1305 | "@types/q": "^0.0.32", 1306 | "@types/selenium-webdriver": "^3.0.0", 1307 | "blocking-proxy": "^1.0.0", 1308 | "browserstack": "^1.5.1", 1309 | "chalk": "^1.1.3", 1310 | "glob": "^7.0.3", 1311 | "jasmine": "2.8.0", 1312 | "jasminewd2": "^2.1.0", 1313 | "optimist": "~0.6.0", 1314 | "q": "1.4.1", 1315 | "saucelabs": "^1.5.0", 1316 | "selenium-webdriver": "3.6.0", 1317 | "source-map-support": "~0.4.0", 1318 | "webdriver-js-extender": "2.1.0", 1319 | "webdriver-manager": "^12.0.6" 1320 | }, 1321 | "dependencies": { 1322 | "chalk": { 1323 | "version": "1.1.3", 1324 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 1325 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 1326 | "dev": true, 1327 | "requires": { 1328 | "ansi-styles": "^2.2.1", 1329 | "escape-string-regexp": "^1.0.2", 1330 | "has-ansi": "^2.0.0", 1331 | "strip-ansi": "^3.0.0", 1332 | "supports-color": "^2.0.0" 1333 | } 1334 | }, 1335 | "strip-ansi": { 1336 | "version": "3.0.1", 1337 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1338 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1339 | "dev": true, 1340 | "requires": { 1341 | "ansi-regex": "^2.0.0" 1342 | } 1343 | }, 1344 | "webdriver-manager": { 1345 | "version": "12.1.7", 1346 | "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.7.tgz", 1347 | "integrity": "sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA==", 1348 | "dev": true, 1349 | "requires": { 1350 | "adm-zip": "^0.4.9", 1351 | "chalk": "^1.1.1", 1352 | "del": "^2.2.0", 1353 | "glob": "^7.0.3", 1354 | "ini": "^1.3.4", 1355 | "minimist": "^1.2.0", 1356 | "q": "^1.4.1", 1357 | "request": "^2.87.0", 1358 | "rimraf": "^2.5.2", 1359 | "semver": "^5.3.0", 1360 | "xml2js": "^0.4.17" 1361 | } 1362 | } 1363 | } 1364 | }, 1365 | "protractor-helper": { 1366 | "version": "4.0.14", 1367 | "resolved": "https://registry.npmjs.org/protractor-helper/-/protractor-helper-4.0.14.tgz", 1368 | "integrity": "sha512-1WaMTf7hwHOMFkxt7/Hd/fhZ/axKC5QZ9jE7UNnpt34unNH9sG92nKlgIjgyi6eMbX6buAh1GXlexcVqZwqIqQ==", 1369 | "dev": true 1370 | }, 1371 | "pseudomap": { 1372 | "version": "1.0.2", 1373 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1374 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 1375 | "dev": true 1376 | }, 1377 | "psl": { 1378 | "version": "1.8.0", 1379 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 1380 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", 1381 | "dev": true 1382 | }, 1383 | "punycode": { 1384 | "version": "2.1.1", 1385 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1386 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1387 | "dev": true 1388 | }, 1389 | "q": { 1390 | "version": "1.4.1", 1391 | "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", 1392 | "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", 1393 | "dev": true 1394 | }, 1395 | "qs": { 1396 | "version": "6.5.2", 1397 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1398 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 1399 | "dev": true 1400 | }, 1401 | "readable-stream": { 1402 | "version": "2.3.7", 1403 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1404 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1405 | "dev": true, 1406 | "requires": { 1407 | "core-util-is": "~1.0.0", 1408 | "inherits": "~2.0.3", 1409 | "isarray": "~1.0.0", 1410 | "process-nextick-args": "~2.0.0", 1411 | "safe-buffer": "~5.1.1", 1412 | "string_decoder": "~1.1.1", 1413 | "util-deprecate": "~1.0.1" 1414 | } 1415 | }, 1416 | "regexpp": { 1417 | "version": "1.1.0", 1418 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", 1419 | "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", 1420 | "dev": true 1421 | }, 1422 | "request": { 1423 | "version": "2.88.2", 1424 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 1425 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 1426 | "dev": true, 1427 | "requires": { 1428 | "aws-sign2": "~0.7.0", 1429 | "aws4": "^1.8.0", 1430 | "caseless": "~0.12.0", 1431 | "combined-stream": "~1.0.6", 1432 | "extend": "~3.0.2", 1433 | "forever-agent": "~0.6.1", 1434 | "form-data": "~2.3.2", 1435 | "har-validator": "~5.1.3", 1436 | "http-signature": "~1.2.0", 1437 | "is-typedarray": "~1.0.0", 1438 | "isstream": "~0.1.2", 1439 | "json-stringify-safe": "~5.0.1", 1440 | "mime-types": "~2.1.19", 1441 | "oauth-sign": "~0.9.0", 1442 | "performance-now": "^2.1.0", 1443 | "qs": "~6.5.2", 1444 | "safe-buffer": "^5.1.2", 1445 | "tough-cookie": "~2.5.0", 1446 | "tunnel-agent": "^0.6.0", 1447 | "uuid": "^3.3.2" 1448 | } 1449 | }, 1450 | "require-uncached": { 1451 | "version": "1.0.3", 1452 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 1453 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 1454 | "dev": true, 1455 | "requires": { 1456 | "caller-path": "^0.1.0", 1457 | "resolve-from": "^1.0.0" 1458 | } 1459 | }, 1460 | "resolve-from": { 1461 | "version": "1.0.1", 1462 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 1463 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 1464 | "dev": true 1465 | }, 1466 | "restore-cursor": { 1467 | "version": "2.0.0", 1468 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 1469 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 1470 | "dev": true, 1471 | "requires": { 1472 | "onetime": "^2.0.0", 1473 | "signal-exit": "^3.0.2" 1474 | } 1475 | }, 1476 | "rimraf": { 1477 | "version": "2.6.3", 1478 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 1479 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 1480 | "dev": true, 1481 | "requires": { 1482 | "glob": "^7.1.3" 1483 | } 1484 | }, 1485 | "run-async": { 1486 | "version": "2.4.0", 1487 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", 1488 | "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", 1489 | "dev": true, 1490 | "requires": { 1491 | "is-promise": "^2.1.0" 1492 | } 1493 | }, 1494 | "rx-lite": { 1495 | "version": "4.0.8", 1496 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", 1497 | "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", 1498 | "dev": true 1499 | }, 1500 | "rx-lite-aggregates": { 1501 | "version": "4.0.8", 1502 | "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", 1503 | "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", 1504 | "dev": true, 1505 | "requires": { 1506 | "rx-lite": "*" 1507 | } 1508 | }, 1509 | "safe-buffer": { 1510 | "version": "5.1.2", 1511 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1512 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1513 | "dev": true 1514 | }, 1515 | "safer-buffer": { 1516 | "version": "2.1.2", 1517 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1518 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1519 | "dev": true 1520 | }, 1521 | "saucelabs": { 1522 | "version": "1.5.0", 1523 | "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", 1524 | "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", 1525 | "dev": true, 1526 | "requires": { 1527 | "https-proxy-agent": "^2.2.1" 1528 | } 1529 | }, 1530 | "sax": { 1531 | "version": "1.2.4", 1532 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1533 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", 1534 | "dev": true 1535 | }, 1536 | "selenium-webdriver": { 1537 | "version": "3.6.0", 1538 | "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", 1539 | "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", 1540 | "dev": true, 1541 | "requires": { 1542 | "jszip": "^3.1.3", 1543 | "rimraf": "^2.5.4", 1544 | "tmp": "0.0.30", 1545 | "xml2js": "^0.4.17" 1546 | }, 1547 | "dependencies": { 1548 | "tmp": { 1549 | "version": "0.0.30", 1550 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", 1551 | "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", 1552 | "dev": true, 1553 | "requires": { 1554 | "os-tmpdir": "~1.0.1" 1555 | } 1556 | } 1557 | } 1558 | }, 1559 | "semver": { 1560 | "version": "5.7.1", 1561 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1562 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1563 | "dev": true 1564 | }, 1565 | "set-immediate-shim": { 1566 | "version": "1.0.1", 1567 | "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", 1568 | "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", 1569 | "dev": true 1570 | }, 1571 | "shebang-command": { 1572 | "version": "1.2.0", 1573 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1574 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1575 | "dev": true, 1576 | "requires": { 1577 | "shebang-regex": "^1.0.0" 1578 | } 1579 | }, 1580 | "shebang-regex": { 1581 | "version": "1.0.0", 1582 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1583 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1584 | "dev": true 1585 | }, 1586 | "signal-exit": { 1587 | "version": "3.0.3", 1588 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 1589 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 1590 | "dev": true 1591 | }, 1592 | "slice-ansi": { 1593 | "version": "1.0.0", 1594 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", 1595 | "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", 1596 | "dev": true, 1597 | "requires": { 1598 | "is-fullwidth-code-point": "^2.0.0" 1599 | } 1600 | }, 1601 | "source-map": { 1602 | "version": "0.5.7", 1603 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1604 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1605 | "dev": true 1606 | }, 1607 | "source-map-support": { 1608 | "version": "0.4.18", 1609 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 1610 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 1611 | "dev": true, 1612 | "requires": { 1613 | "source-map": "^0.5.6" 1614 | } 1615 | }, 1616 | "sprintf-js": { 1617 | "version": "1.0.3", 1618 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1619 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1620 | "dev": true 1621 | }, 1622 | "sshpk": { 1623 | "version": "1.16.1", 1624 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 1625 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 1626 | "dev": true, 1627 | "requires": { 1628 | "asn1": "~0.2.3", 1629 | "assert-plus": "^1.0.0", 1630 | "bcrypt-pbkdf": "^1.0.0", 1631 | "dashdash": "^1.12.0", 1632 | "ecc-jsbn": "~0.1.1", 1633 | "getpass": "^0.1.1", 1634 | "jsbn": "~0.1.0", 1635 | "safer-buffer": "^2.0.2", 1636 | "tweetnacl": "~0.14.0" 1637 | } 1638 | }, 1639 | "string-width": { 1640 | "version": "2.1.1", 1641 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1642 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1643 | "dev": true, 1644 | "requires": { 1645 | "is-fullwidth-code-point": "^2.0.0", 1646 | "strip-ansi": "^4.0.0" 1647 | } 1648 | }, 1649 | "string_decoder": { 1650 | "version": "1.1.1", 1651 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1652 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1653 | "dev": true, 1654 | "requires": { 1655 | "safe-buffer": "~5.1.0" 1656 | } 1657 | }, 1658 | "strip-ansi": { 1659 | "version": "4.0.0", 1660 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1661 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1662 | "dev": true, 1663 | "requires": { 1664 | "ansi-regex": "^3.0.0" 1665 | }, 1666 | "dependencies": { 1667 | "ansi-regex": { 1668 | "version": "3.0.0", 1669 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1670 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 1671 | "dev": true 1672 | } 1673 | } 1674 | }, 1675 | "strip-json-comments": { 1676 | "version": "2.0.1", 1677 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1678 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1679 | "dev": true 1680 | }, 1681 | "supports-color": { 1682 | "version": "2.0.0", 1683 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1684 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1685 | "dev": true 1686 | }, 1687 | "table": { 1688 | "version": "4.0.2", 1689 | "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", 1690 | "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", 1691 | "dev": true, 1692 | "requires": { 1693 | "ajv": "^5.2.3", 1694 | "ajv-keywords": "^2.1.0", 1695 | "chalk": "^2.1.0", 1696 | "lodash": "^4.17.4", 1697 | "slice-ansi": "1.0.0", 1698 | "string-width": "^2.1.1" 1699 | } 1700 | }, 1701 | "text-table": { 1702 | "version": "0.2.0", 1703 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1704 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1705 | "dev": true 1706 | }, 1707 | "through": { 1708 | "version": "2.3.8", 1709 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1710 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1711 | "dev": true 1712 | }, 1713 | "tmp": { 1714 | "version": "0.0.33", 1715 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1716 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1717 | "dev": true, 1718 | "requires": { 1719 | "os-tmpdir": "~1.0.2" 1720 | } 1721 | }, 1722 | "tough-cookie": { 1723 | "version": "2.5.0", 1724 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 1725 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 1726 | "dev": true, 1727 | "requires": { 1728 | "psl": "^1.1.28", 1729 | "punycode": "^2.1.1" 1730 | } 1731 | }, 1732 | "tunnel-agent": { 1733 | "version": "0.6.0", 1734 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1735 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1736 | "dev": true, 1737 | "requires": { 1738 | "safe-buffer": "^5.0.1" 1739 | } 1740 | }, 1741 | "tweetnacl": { 1742 | "version": "0.14.5", 1743 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1744 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1745 | "dev": true 1746 | }, 1747 | "type-check": { 1748 | "version": "0.3.2", 1749 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1750 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1751 | "dev": true, 1752 | "requires": { 1753 | "prelude-ls": "~1.1.2" 1754 | } 1755 | }, 1756 | "typedarray": { 1757 | "version": "0.0.6", 1758 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1759 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1760 | "dev": true 1761 | }, 1762 | "uri-js": { 1763 | "version": "4.2.2", 1764 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1765 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1766 | "dev": true, 1767 | "requires": { 1768 | "punycode": "^2.1.0" 1769 | } 1770 | }, 1771 | "util-deprecate": { 1772 | "version": "1.0.2", 1773 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1774 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1775 | "dev": true 1776 | }, 1777 | "uuid": { 1778 | "version": "3.4.0", 1779 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 1780 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 1781 | "dev": true 1782 | }, 1783 | "verror": { 1784 | "version": "1.10.0", 1785 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1786 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1787 | "dev": true, 1788 | "requires": { 1789 | "assert-plus": "^1.0.0", 1790 | "core-util-is": "1.0.2", 1791 | "extsprintf": "^1.2.0" 1792 | } 1793 | }, 1794 | "webdriver-js-extender": { 1795 | "version": "2.1.0", 1796 | "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", 1797 | "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", 1798 | "dev": true, 1799 | "requires": { 1800 | "@types/selenium-webdriver": "^3.0.0", 1801 | "selenium-webdriver": "^3.0.1" 1802 | } 1803 | }, 1804 | "which": { 1805 | "version": "1.3.1", 1806 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1807 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1808 | "dev": true, 1809 | "requires": { 1810 | "isexe": "^2.0.0" 1811 | } 1812 | }, 1813 | "word-wrap": { 1814 | "version": "1.2.3", 1815 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1816 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1817 | "dev": true 1818 | }, 1819 | "wordwrap": { 1820 | "version": "0.0.3", 1821 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 1822 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", 1823 | "dev": true 1824 | }, 1825 | "wrappy": { 1826 | "version": "1.0.2", 1827 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1828 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1829 | "dev": true 1830 | }, 1831 | "write": { 1832 | "version": "0.2.1", 1833 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 1834 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 1835 | "dev": true, 1836 | "requires": { 1837 | "mkdirp": "^0.5.1" 1838 | } 1839 | }, 1840 | "xml2js": { 1841 | "version": "0.4.23", 1842 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", 1843 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", 1844 | "dev": true, 1845 | "requires": { 1846 | "sax": ">=0.6.0", 1847 | "xmlbuilder": "~11.0.0" 1848 | } 1849 | }, 1850 | "xmlbuilder": { 1851 | "version": "11.0.1", 1852 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 1853 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", 1854 | "dev": true 1855 | }, 1856 | "yallist": { 1857 | "version": "2.1.2", 1858 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 1859 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 1860 | "dev": true 1861 | } 1862 | } 1863 | } 1864 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protractor-components-and-page-objects", 3 | "version": "1.0.0", 4 | "description": "project to demonstrate protractor tests using the concept of components and page objects", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/wlsf82/protractor-components-and-page-objects" 8 | }, 9 | "scripts": { 10 | "lint": "eslint test/**/*.js && eslint test/**/**/*.js", 11 | "lint:fix": "eslint test/**/*.js --fix && eslint test/**/**/*.js --fix", 12 | "pretest": "webdriver-manager update --gecko false", 13 | "test": "protractor test/e2e/protractor.conf.js" 14 | }, 15 | "keywords": [ 16 | "protractor", 17 | "components", 18 | "page-objects", 19 | "testing" 20 | ], 21 | "author": "Walmyr Filho (http://walmyr-filho.com)", 22 | "license": "MIT", 23 | "devDependencies": { 24 | "eslint": "^4.18.1", 25 | "jasmine-spec-reporter": "^4.2.1", 26 | "protractor": "^5.4.2", 27 | "protractor-helper": "^4.0.14" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/e2e/components/Form.js: -------------------------------------------------------------------------------- 1 | const helper = require("protractor-helper"); 2 | 3 | class Form { 4 | constructor() { 5 | this._parentElement = element(by.css("form")); 6 | 7 | this._nameField = this._parentElement.element(by.css(".fields #name")); 8 | this._descriptionField = this._parentElement.element( 9 | by.css(".fields #description") 10 | ); 11 | this._imageUrlField = this._parentElement.element(by.css(".fields #image-url")); 12 | this._cancelButton = this._parentElement.element( 13 | by.css(".actions .cancel-button") 14 | ); 15 | this._submitButton = this._parentElement.element( 16 | by.css(".actions input[type='submit']") 17 | ); 18 | } 19 | 20 | get nameField() { 21 | return this._nameField; 22 | } 23 | 24 | get descriptionField() { 25 | return this._descriptionField; 26 | } 27 | 28 | get imageUrlField() { 29 | return this._imageUrlField; 30 | } 31 | 32 | get cancelButton() { 33 | return this._cancelButton; 34 | } 35 | 36 | get submitButton() { 37 | return this._submitButton; 38 | } 39 | 40 | fillWithDataAndSubmit(data) { 41 | helper.fillFieldWithText(this.nameField, data.name); 42 | helper.fillFieldWithText(this.descriptionField, data.description); 43 | helper.fillFieldWithText(this.imageUrlField, data.imageUrlValue); 44 | helper.click(this.submitButton); 45 | } 46 | } 47 | 48 | module.exports = Form; 49 | -------------------------------------------------------------------------------- /test/e2e/components/Header.js: -------------------------------------------------------------------------------- 1 | class Header { 2 | constructor() { 3 | this._parentElement = element(by.css("header")); 4 | 5 | this._heading = this._parentElement.element(by.css("h1")); 6 | } 7 | 8 | get heading() { 9 | return this._heading; 10 | } 11 | } 12 | 13 | module.exports = Header; 14 | -------------------------------------------------------------------------------- /test/e2e/components/Preview.js: -------------------------------------------------------------------------------- 1 | class Preview { 2 | constructor() { 3 | this._parentElement = element(by.css(".preview")); 4 | 5 | this._title = this._parentElement.element(by.css("h1")); 6 | this._image = this._parentElement.element(by.css("img")); 7 | } 8 | 9 | get title() { 10 | return this._title; 11 | } 12 | 13 | get image() { 14 | return this._image; 15 | } 16 | } 17 | 18 | module.exports = Preview; 19 | -------------------------------------------------------------------------------- /test/e2e/page-objects/CreateImage.js: -------------------------------------------------------------------------------- 1 | const FormComponent = require("../components/Form"); 2 | const HeaderComponent = require("../components/Header"); 3 | const PreviewComponent = require("../components/Preview"); 4 | 5 | class CreateImage { 6 | constructor() { 7 | this._relativeUrl = "/create-image"; 8 | 9 | this.header = new HeaderComponent(); 10 | this.form = new FormComponent(); 11 | this.preview = new PreviewComponent(); 12 | } 13 | 14 | get relativeUrl() { 15 | return this._relativeUrl; 16 | } 17 | } 18 | 19 | module.exports = CreateImage; 20 | -------------------------------------------------------------------------------- /test/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | const SpecReporter = require("jasmine-spec-reporter").SpecReporter; 2 | 3 | module.exports.config = { 4 | directConnect: true, 5 | capabilities: { 6 | browserName: "chrome", 7 | chromeOptions: { 8 | args: ["--headless", "--disable-gpu", "--window-size=1024,768"] 9 | } 10 | }, 11 | baseUrl: "https://example.com", 12 | specs: ["specs/*.spec.js"], 13 | onPrepare: () => { 14 | browser.waitForAngularEnabled(false); 15 | jasmine.getEnv().addReporter( 16 | new SpecReporter({ 17 | displayFailuresSummary: true, 18 | displayFailedSpec: true, 19 | displaySuiteNumber: true, 20 | displaySpecDuration: true 21 | }) 22 | ); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /test/e2e/specs/createImage.spec.js: -------------------------------------------------------------------------------- 1 | const helper = require("protractor-helper"); 2 | 3 | const CreateImagePage = require("../page-objects/CreateImage"); 4 | 5 | describe("Given I access the relative URL '/create-image'", () => { 6 | const createImagePage = new CreateImagePage(); 7 | 8 | beforeEach(() => browser.get(createImagePage.relativeUrl)); 9 | 10 | describe("Happy path", () => { 11 | describe("When I fill the image URL field with a valid value", () => { 12 | const imageUrlValue = "http://example.com/some-image.png"; 13 | 14 | beforeEach(() => 15 | helper.fillFieldWithText( 16 | createImagePage.form.imageUrlField, 17 | imageUrlValue 18 | ) 19 | ); 20 | 21 | it("Then the image preview element uses the provided value in the 'src' attribute", () => { 22 | expect(createImagePage.preview.image.getAttribute("src")).toEqual( 23 | imageUrlValue 24 | ); 25 | }); 26 | }); 27 | 28 | describe("When I click the header's heading", () => { 29 | beforeEach(() => helper.click(createImagePage.header.heading)); 30 | 31 | it("Then I'm redirected to the home page", () => { 32 | helper.waitForUrlToBeEqualToExpectedUrl(browser.baseUrl); 33 | }); 34 | }); 35 | 36 | describe("When I submit the form with valid data", () => { 37 | let data; 38 | 39 | beforeEach(() => { 40 | data = { 41 | name: "Magic cube", 42 | description: "The nicest toy ever.", 43 | imageUrlValue: "http://example.com/magic-cube.png" 44 | }; 45 | 46 | createImagePage.form.fillWithDataAndSubmit(data); 47 | }); 48 | 49 | it("Then all fields are cleared and a success message is shown", () => { 50 | helper.waitForTextNotToBePresentInElement( 51 | createImagePage.form.nameField, 52 | data.name 53 | ); 54 | helper.waitForTextNotToBePresentInElement( 55 | createImagePage.form.descriptionField, 56 | data.description 57 | ); 58 | helper.waitForTextNotToBePresentInElement( 59 | createImagePage.form.imageUrlField, 60 | data.imageUrlValue 61 | ); 62 | 63 | const successMessage = element(by.css(".success-message")); 64 | 65 | helper.waitForElementVisibility(successMessage); 66 | }); 67 | }); 68 | }); 69 | 70 | describe("Alternate paths", () => { 71 | describe("When I submit the form without filling the name, description, and image URL", () => { 72 | it("Then all required fields are shown in red, meaning error", () => { 73 | helper.click(createImagePage.form.submitButton); 74 | 75 | expect( 76 | createImagePage.form.nameField.getCssValue("background-color") 77 | ).toEqual("rgb(255,0,0)"); 78 | expect( 79 | createImagePage.form.descriptionField.getCssValue("background-color") 80 | ).toEqual("rgb(255,0,0)"); 81 | expect( 82 | createImagePage.form.imageUrlField.getCssValue("background-color") 83 | ).toEqual("rgb(255,0,0)"); 84 | }); 85 | }); 86 | 87 | describe("When I submit the form with a name and description, but a missing image URL", () => { 88 | beforeEach(() => { 89 | const dataSetWithMissingImageUrl = { 90 | name: "Boo", 91 | description: "The nicest kid! From Monters Inc.", 92 | imageUrlValue: "" 93 | }; 94 | 95 | createImagePage.form.fillWithDataAndSubmit(dataSetWithMissingImageUrl); 96 | }); 97 | 98 | it("Then the required field (image URL) is shown in red, meaning error", () => { 99 | expect( 100 | createImagePage.form.imageUrlField.getCssValue("background-color") 101 | ).toEqual("rgb(255,0,0)"); 102 | }); 103 | }); 104 | }); 105 | }); 106 | --------------------------------------------------------------------------------