diff --git a/.travis.yml b/.travis.yml index 1e3b6a9f..ec119b78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: node_js node_js: + - "8" - "7" - "6" - "5.1" @@ -12,6 +13,8 @@ script: - grunt - npm run test:unit - npm run test:e2e +after_script: + - npm list cache: directories: - node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index ef24a46e..9a68b174 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,20 +5,33 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [2.1.3] - Unreleased ### Changed +- Remove Roboto fonts files inside `fonts` and these are installed by npm install command. ### Added - Add `clientonly` script to start only the electron client for a remote server. - Add symbol and color properties of event when `CALENDAR_EVENTS` notification is broadcasted from `default/calendar` module. -- Add `.vscode/` folder to `.gitignore` to keep custom Visual Studio Code config out of git +- Add `.vscode/` folder to `.gitignore` to keep custom Visual Studio Code config out of git. +- Add unit test the capitalizeFirstLetter function of newfeed module. +- Add new unit tests for function `shorten` in calendar module. +- Add new unit tests for function `getLocaleSpecification` in calendar module. +- Add unit test for js/class.js. +- Add unit tests for function `roundValue` in currentweather module. +- Add test e2e showWeek feature in spanish language. - Add warning Log when is used old authentication method in the calendar module. ### Updated -- Changed 'default.js' - listen on all attached interfaces by default +- Changed 'default.js' - listen on all attached interfaces by default. +- Add execution of `npm list` after the test are ran in Travis CI. +- Change hooks for the vendors e2e tests. +- Add log when clientonly failed on starting. +- Add warning color when are using full ip whitelist. ### Fixed - -- Fixed issue with incorrect allignment of analog clock when displayed in the center column of the MM -- Fixed ipWhitelist behaviour to make empty whitelist ([]) allow any and all hosts access to the MM +- Fixed issue with incorrect allignment of analog clock when displayed in the center column of the MM. +- Fixed ipWhitelist behaviour to make empty whitelist ([]) allow any and all hosts access to the MM. +- Fixed issue with calendar module where 'excludedEvents' count towards 'maximumEntries'. +- Fixed issue with calendar module where global configuration of maximumEntries was not overridden by calendar specific config (see module doc). +- Fixed issue where `this.file(filename)` returns a path with two hashes ## [2.1.2] - 2017-07-01 @@ -48,7 +61,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Updated - Added missing keys to Polish translation. - Added missing key to German translation. -- Added better translation with flexible word order to Finnish translation +- Added better translation with flexible word order to Finnish translation. ### Fixed - Fix instruction in README for using automatically installer script. @@ -56,8 +69,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Fix double message about port when server is starting - Corrected Swedish translations for TODAY/TOMORROW/DAYAFTERTOMORROW. - Removed unused import from js/electron.js -- Made calendar.js respect config.timeFormat irrespecive of locale setting -- Fixed alignment of analog clock when a large calendar is displayed in the same side bar +- Made calendar.js respect config.timeFormat irrespecive of locale setting. +- Fixed alignment of analog clock when a large calendar is displayed in the same side bar. ## [2.1.1] - 2017-04-01 @@ -65,18 +78,18 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Add `anytime` group for Compliments module. -- Compliments module can use remoteFile without default daytime arrays defined +- Compliments module can use remoteFile without default daytime arrays defined. - Installer: Use init config.js from config.js.sample. - Switched out `rrule` package for `rrule-alt` and fixes in `ical.js` in order to fix calendar issues. ([#565](https://github.com/MichMich/MagicMirror/issues/565)) - Make mouse events pass through the region fullscreen_above to modules below. - Scaled the splash screen down to make it a bit more subtle. - Replace HTML tables with markdown tables in README files. - Added `DAYAFTERTOMORROW`, `UPDATE_NOTIFICATION` and `UPDATE_NOTIFICATION_MODULE` to Finnish translations. -- Run `npm test` on Travis automatically +- Run `npm test` on Travis automatically. - Show the splash screen image even when is reboot or halted. - Added some missing translaton strings in the sv.json file. - Run task jsonlint to check translation files. -- Restructured Test Suite +- Restructured Test Suite. ### Added - Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673)). diff --git a/clientonly/index.js b/clientonly/index.js index 750a98e6..72495504 100644 --- a/clientonly/index.js +++ b/clientonly/index.js @@ -87,6 +87,13 @@ child.on("error", function (err) { process.stdout.write(`Client: ${err}`); }); + + child.on('close', (code) => { + if (code != 0) { + console.log(`There something wrong. The clientonly is not running code ${code}`); + } + }); + }) .catch(function (reason) { fail(`Unable to connect to server: (${reason})`); @@ -94,4 +101,4 @@ } else { fail(); } -}()); \ No newline at end of file +}()); diff --git a/fonts/LICENSE.txt b/fonts/LICENSE.txt deleted file mode 100644 index 75b52484..00000000 --- a/fonts/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/fonts/Roboto-Black/Roboto-Black.ttf b/fonts/Roboto-Black/Roboto-Black.ttf deleted file mode 100644 index fbde625d..00000000 Binary files a/fonts/Roboto-Black/Roboto-Black.ttf and /dev/null differ diff --git a/fonts/Roboto-Black/Roboto-Black.woff b/fonts/Roboto-Black/Roboto-Black.woff deleted file mode 100644 index 94b19305..00000000 Binary files a/fonts/Roboto-Black/Roboto-Black.woff and /dev/null differ diff --git a/fonts/Roboto-Black/Roboto-Black.woff2 b/fonts/Roboto-Black/Roboto-Black.woff2 deleted file mode 100644 index c0cb786e..00000000 Binary files a/fonts/Roboto-Black/Roboto-Black.woff2 and /dev/null differ diff --git a/fonts/Roboto-BlackItalic/Roboto-BlackItalic.ttf b/fonts/Roboto-BlackItalic/Roboto-BlackItalic.ttf deleted file mode 100644 index 60f7782a..00000000 Binary files a/fonts/Roboto-BlackItalic/Roboto-BlackItalic.ttf and /dev/null differ diff --git a/fonts/Roboto-BlackItalic/Roboto-BlackItalic.woff b/fonts/Roboto-BlackItalic/Roboto-BlackItalic.woff deleted file mode 100644 index eb07f101..00000000 Binary files a/fonts/Roboto-BlackItalic/Roboto-BlackItalic.woff and /dev/null differ diff --git a/fonts/Roboto-BlackItalic/Roboto-BlackItalic.woff2 b/fonts/Roboto-BlackItalic/Roboto-BlackItalic.woff2 deleted file mode 100644 index 6ad4604f..00000000 Binary files a/fonts/Roboto-BlackItalic/Roboto-BlackItalic.woff2 and /dev/null differ diff --git a/fonts/Roboto-Bold/Roboto-Bold.ttf b/fonts/Roboto-Bold/Roboto-Bold.ttf deleted file mode 100644 index a355c27c..00000000 Binary files a/fonts/Roboto-Bold/Roboto-Bold.ttf and /dev/null differ diff --git a/fonts/Roboto-Bold/Roboto-Bold.woff b/fonts/Roboto-Bold/Roboto-Bold.woff deleted file mode 100644 index d1ef48b4..00000000 Binary files a/fonts/Roboto-Bold/Roboto-Bold.woff and /dev/null differ diff --git a/fonts/Roboto-Bold/Roboto-Bold.woff2 b/fonts/Roboto-Bold/Roboto-Bold.woff2 deleted file mode 100644 index 5658e9a7..00000000 Binary files a/fonts/Roboto-Bold/Roboto-Bold.woff2 and /dev/null differ diff --git a/fonts/Roboto-BoldItalic/Roboto-BoldItalic.ttf b/fonts/Roboto-BoldItalic/Roboto-BoldItalic.ttf deleted file mode 100644 index 3c9a7a37..00000000 Binary files a/fonts/Roboto-BoldItalic/Roboto-BoldItalic.ttf and /dev/null differ diff --git a/fonts/Roboto-BoldItalic/Roboto-BoldItalic.woff b/fonts/Roboto-BoldItalic/Roboto-BoldItalic.woff deleted file mode 100644 index 291c89dd..00000000 Binary files a/fonts/Roboto-BoldItalic/Roboto-BoldItalic.woff and /dev/null differ diff --git a/fonts/Roboto-BoldItalic/Roboto-BoldItalic.woff2 b/fonts/Roboto-BoldItalic/Roboto-BoldItalic.woff2 deleted file mode 100644 index 75123709..00000000 Binary files a/fonts/Roboto-BoldItalic/Roboto-BoldItalic.woff2 and /dev/null differ diff --git a/fonts/Roboto-Italic/Roboto-Italic.ttf b/fonts/Roboto-Italic/Roboto-Italic.ttf deleted file mode 100644 index ff6046d5..00000000 Binary files a/fonts/Roboto-Italic/Roboto-Italic.ttf and /dev/null differ diff --git a/fonts/Roboto-Italic/Roboto-Italic.woff b/fonts/Roboto-Italic/Roboto-Italic.woff deleted file mode 100644 index 3bd43138..00000000 Binary files a/fonts/Roboto-Italic/Roboto-Italic.woff and /dev/null differ diff --git a/fonts/Roboto-Italic/Roboto-Italic.woff2 b/fonts/Roboto-Italic/Roboto-Italic.woff2 deleted file mode 100644 index 77c81227..00000000 Binary files a/fonts/Roboto-Italic/Roboto-Italic.woff2 and /dev/null differ diff --git a/fonts/Roboto-Light/Roboto-Light.ttf b/fonts/Roboto-Light/Roboto-Light.ttf deleted file mode 100644 index 94c6bcc6..00000000 Binary files a/fonts/Roboto-Light/Roboto-Light.ttf and /dev/null differ diff --git a/fonts/Roboto-Light/Roboto-Light.woff b/fonts/Roboto-Light/Roboto-Light.woff deleted file mode 100644 index 1d1ad478..00000000 Binary files a/fonts/Roboto-Light/Roboto-Light.woff and /dev/null differ diff --git a/fonts/Roboto-Light/Roboto-Light.woff2 b/fonts/Roboto-Light/Roboto-Light.woff2 deleted file mode 100644 index 166c8218..00000000 Binary files a/fonts/Roboto-Light/Roboto-Light.woff2 and /dev/null differ diff --git a/fonts/Roboto-LightItalic/Roboto-LightItalic.ttf b/fonts/Roboto-LightItalic/Roboto-LightItalic.ttf deleted file mode 100644 index 04cc0023..00000000 Binary files a/fonts/Roboto-LightItalic/Roboto-LightItalic.ttf and /dev/null differ diff --git a/fonts/Roboto-LightItalic/Roboto-LightItalic.woff b/fonts/Roboto-LightItalic/Roboto-LightItalic.woff deleted file mode 100644 index 3662bf40..00000000 Binary files a/fonts/Roboto-LightItalic/Roboto-LightItalic.woff and /dev/null differ diff --git a/fonts/Roboto-LightItalic/Roboto-LightItalic.woff2 b/fonts/Roboto-LightItalic/Roboto-LightItalic.woff2 deleted file mode 100644 index 9ba7fbd2..00000000 Binary files a/fonts/Roboto-LightItalic/Roboto-LightItalic.woff2 and /dev/null differ diff --git a/fonts/Roboto-Medium/Roboto-Medium.ttf b/fonts/Roboto-Medium/Roboto-Medium.ttf deleted file mode 100644 index 39c63d74..00000000 Binary files a/fonts/Roboto-Medium/Roboto-Medium.ttf and /dev/null differ diff --git a/fonts/Roboto-Medium/Roboto-Medium.woff b/fonts/Roboto-Medium/Roboto-Medium.woff deleted file mode 100644 index 487ea69b..00000000 Binary files a/fonts/Roboto-Medium/Roboto-Medium.woff and /dev/null differ diff --git a/fonts/Roboto-Medium/Roboto-Medium.woff2 b/fonts/Roboto-Medium/Roboto-Medium.woff2 deleted file mode 100644 index 2622b475..00000000 Binary files a/fonts/Roboto-Medium/Roboto-Medium.woff2 and /dev/null differ diff --git a/fonts/Roboto-MediumItalic/Roboto-MediumItalic.ttf b/fonts/Roboto-MediumItalic/Roboto-MediumItalic.ttf deleted file mode 100644 index dc743f0a..00000000 Binary files a/fonts/Roboto-MediumItalic/Roboto-MediumItalic.ttf and /dev/null differ diff --git a/fonts/Roboto-MediumItalic/Roboto-MediumItalic.woff b/fonts/Roboto-MediumItalic/Roboto-MediumItalic.woff deleted file mode 100644 index 70dea35a..00000000 Binary files a/fonts/Roboto-MediumItalic/Roboto-MediumItalic.woff and /dev/null differ diff --git a/fonts/Roboto-MediumItalic/Roboto-MediumItalic.woff2 b/fonts/Roboto-MediumItalic/Roboto-MediumItalic.woff2 deleted file mode 100644 index 8b111d46..00000000 Binary files a/fonts/Roboto-MediumItalic/Roboto-MediumItalic.woff2 and /dev/null differ diff --git a/fonts/Roboto-Regular/Roboto-Regular.ttf b/fonts/Roboto-Regular/Roboto-Regular.ttf deleted file mode 100644 index 8c082c8d..00000000 Binary files a/fonts/Roboto-Regular/Roboto-Regular.ttf and /dev/null differ diff --git a/fonts/Roboto-Regular/Roboto-Regular.woff b/fonts/Roboto-Regular/Roboto-Regular.woff deleted file mode 100644 index 6ea53c20..00000000 Binary files a/fonts/Roboto-Regular/Roboto-Regular.woff and /dev/null differ diff --git a/fonts/Roboto-Regular/Roboto-Regular.woff2 b/fonts/Roboto-Regular/Roboto-Regular.woff2 deleted file mode 100644 index 10cf92b8..00000000 Binary files a/fonts/Roboto-Regular/Roboto-Regular.woff2 and /dev/null differ diff --git a/fonts/Roboto-Thin/Roboto-Thin.ttf b/fonts/Roboto-Thin/Roboto-Thin.ttf deleted file mode 100644 index d6955502..00000000 Binary files a/fonts/Roboto-Thin/Roboto-Thin.ttf and /dev/null differ diff --git a/fonts/Roboto-Thin/Roboto-Thin.woff b/fonts/Roboto-Thin/Roboto-Thin.woff deleted file mode 100644 index b0e7c557..00000000 Binary files a/fonts/Roboto-Thin/Roboto-Thin.woff and /dev/null differ diff --git a/fonts/Roboto-Thin/Roboto-Thin.woff2 b/fonts/Roboto-Thin/Roboto-Thin.woff2 deleted file mode 100644 index 5eee3b3e..00000000 Binary files a/fonts/Roboto-Thin/Roboto-Thin.woff2 and /dev/null differ diff --git a/fonts/Roboto-ThinItalic/Roboto-ThinItalic.ttf b/fonts/Roboto-ThinItalic/Roboto-ThinItalic.ttf deleted file mode 100644 index 07172ff6..00000000 Binary files a/fonts/Roboto-ThinItalic/Roboto-ThinItalic.ttf and /dev/null differ diff --git a/fonts/Roboto-ThinItalic/Roboto-ThinItalic.woff b/fonts/Roboto-ThinItalic/Roboto-ThinItalic.woff deleted file mode 100644 index 73f10ad4..00000000 Binary files a/fonts/Roboto-ThinItalic/Roboto-ThinItalic.woff and /dev/null differ diff --git a/fonts/Roboto-ThinItalic/Roboto-ThinItalic.woff2 b/fonts/Roboto-ThinItalic/Roboto-ThinItalic.woff2 deleted file mode 100644 index 292c86f4..00000000 Binary files a/fonts/Roboto-ThinItalic/Roboto-ThinItalic.woff2 and /dev/null differ diff --git a/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.ttf b/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.ttf deleted file mode 100644 index fc28868a..00000000 Binary files a/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.ttf and /dev/null differ diff --git a/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.woff b/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.woff deleted file mode 100644 index cf577ca5..00000000 Binary files a/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.woff and /dev/null differ diff --git a/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.woff2 b/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.woff2 deleted file mode 100644 index 8b2e28cd..00000000 Binary files a/fonts/RobotoCondensed-Bold/RobotoCondensed-Bold.woff2 and /dev/null differ diff --git a/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.ttf b/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.ttf deleted file mode 100644 index e1a648ff..00000000 Binary files a/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.ttf and /dev/null differ diff --git a/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.woff b/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.woff deleted file mode 100644 index 0b5db116..00000000 Binary files a/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.woff and /dev/null differ diff --git a/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.woff2 b/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.woff2 deleted file mode 100644 index 5d3f2072..00000000 Binary files a/fonts/RobotoCondensed-BoldItalic/RobotoCondensed-BoldItalic.woff2 and /dev/null differ diff --git a/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.ttf b/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.ttf deleted file mode 100644 index 97ff9f1e..00000000 Binary files a/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.ttf and /dev/null differ diff --git a/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.woff b/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.woff deleted file mode 100644 index 4548bfa9..00000000 Binary files a/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.woff and /dev/null differ diff --git a/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.woff2 b/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.woff2 deleted file mode 100644 index 04141901..00000000 Binary files a/fonts/RobotoCondensed-Italic/RobotoCondensed-Italic.woff2 and /dev/null differ diff --git a/fonts/RobotoCondensed-Light/RobotoCondensed-Light.ttf b/fonts/RobotoCondensed-Light/RobotoCondensed-Light.ttf deleted file mode 100644 index 2dae31e2..00000000 Binary files a/fonts/RobotoCondensed-Light/RobotoCondensed-Light.ttf and /dev/null differ diff --git a/fonts/RobotoCondensed-Light/RobotoCondensed-Light.woff b/fonts/RobotoCondensed-Light/RobotoCondensed-Light.woff deleted file mode 100644 index b797af13..00000000 Binary files a/fonts/RobotoCondensed-Light/RobotoCondensed-Light.woff and /dev/null differ diff --git a/fonts/RobotoCondensed-Light/RobotoCondensed-Light.woff2 b/fonts/RobotoCondensed-Light/RobotoCondensed-Light.woff2 deleted file mode 100644 index 1e3b487a..00000000 Binary files a/fonts/RobotoCondensed-Light/RobotoCondensed-Light.woff2 and /dev/null differ diff --git a/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.ttf b/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.ttf deleted file mode 100644 index da108d3a..00000000 Binary files a/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.ttf and /dev/null differ diff --git a/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.woff b/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.woff deleted file mode 100644 index 8eae55a8..00000000 Binary files a/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.woff and /dev/null differ diff --git a/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.woff2 b/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.woff2 deleted file mode 100644 index 947a1358..00000000 Binary files a/fonts/RobotoCondensed-LightItalic/RobotoCondensed-LightItalic.woff2 and /dev/null differ diff --git a/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.ttf b/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.ttf deleted file mode 100644 index c2304c14..00000000 Binary files a/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.ttf and /dev/null differ diff --git a/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.woff b/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.woff deleted file mode 100644 index 3e25d65d..00000000 Binary files a/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.woff and /dev/null differ diff --git a/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.woff2 b/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.woff2 deleted file mode 100644 index d7c42c8c..00000000 Binary files a/fonts/RobotoCondensed-Regular/RobotoCondensed-Regular.woff2 and /dev/null differ diff --git a/fonts/package.json b/fonts/package.json new file mode 100644 index 00000000..ad164516 --- /dev/null +++ b/fonts/package.json @@ -0,0 +1,15 @@ +{ + "name": "magicmirror-fonts", + "description": "Package for fonts use by MagicMirror Core.", + "repository": { + "type": "git", + "url": "git+https://github.com/MichMich/MagicMirror.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/MichMich/MagicMirror/issues" + }, + "dependencies": { + "roboto-fontface": "^0.8.0" + } +} diff --git a/fonts/roboto.css b/fonts/roboto.css index ce9099da..fda90cd2 100644 --- a/fonts/roboto.css +++ b/fonts/roboto.css @@ -5,9 +5,9 @@ src: local("Roboto Thin"), local("Roboto-Thin"), - url("Roboto-Thin/Roboto-Thin.woff2") format("woff2"), - url("Roboto-Thin/Roboto-Thin.woff") format("woff"), - url("Roboto-Thin/Roboto-Thin.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin/Roboto-Thin.ttf") format("truetype"); } @font-face { @@ -17,9 +17,9 @@ src: local("Roboto Condensed Light"), local("RobotoCondensed-Light"), - url("RobotoCondensed-Light/RobotoCondensed-Light.woff2") format("woff2"), - url("RobotoCondensed-Light/RobotoCondensed-Light.woff") format("woff"), - url("RobotoCondensed-Light/RobotoCondensed-Light.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Light.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Light.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Light.ttf") format("truetype"); } @font-face { @@ -29,9 +29,9 @@ src: local("Roboto Condensed"), local("RobotoCondensed-Regular"), - url("RobotoCondensed-Regular/RobotoCondensed-Regular.woff2") format("woff2"), - url("RobotoCondensed-Regular/RobotoCondensed-Regular.woff") format("woff"), - url("RobotoCondensed-Regular/RobotoCondensed-Regular.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Regular.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Regular.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Regular.ttf") format("truetype"); } @font-face { @@ -41,9 +41,9 @@ src: local("Roboto Condensed Bold"), local("RobotoCondensed-Bold"), - url("RobotoCondensed-Bold/RobotoCondensed-Bold.woff2") format("woff2"), - url("RobotoCondensed-Bold/RobotoCondensed-Bold.woff") format("woff"), - url("RobotoCondensed-Bold/RobotoCondensed-Bold.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Bold.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Bold.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto-condensed/RobotoCondensed-Bold.ttf") format("truetype"); } @font-face { @@ -53,9 +53,9 @@ src: local("Roboto"), local("Roboto-Regular"), - url("Roboto-Regular/Roboto-Regular.woff2") format("woff2"), - url("Roboto-Regular/Roboto-Regular.woff") format("woff"), - url("Roboto-Regular/Roboto-Regular.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.ttf") format("truetype"); } @font-face { @@ -65,9 +65,9 @@ src: local("Roboto Medium"), local("Roboto-Medium"), - url("Roboto-Medium/Roboto-Medium.woff2") format("woff2"), - url("Roboto-Medium/Roboto-Medium.woff") format("woff"), - url("Roboto-Medium/Roboto-Medium.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.ttf") format("truetype"); } @font-face { @@ -77,9 +77,9 @@ src: local("Roboto Bold"), local("Roboto-Bold"), - url("Roboto-Bold/Roboto-Bold.woff2") format("woff2"), - url("Roboto-Bold/Roboto-Bold.woff") format("woff"), - url("Roboto-Bold/Roboto-Bold.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.ttf") format("truetype"); } @font-face { @@ -89,7 +89,7 @@ src: local("Roboto Light"), local("Roboto-Light"), - url("Roboto-Light/Roboto-Light.woff2") format("woff2"), - url("Roboto-Light/Roboto-Light.woff") format("woff"), - url("Roboto-Light/Roboto-Light.ttf") format("truetype"); + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff2") format("woff2"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff") format("woff"), + url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.ttf") format("truetype"); } diff --git a/index.html b/index.html index 85951a85..f3e8d12f 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,7 @@ - Magic Mirror + MagicMirror² diff --git a/js/class.js b/js/class.js index f2fa5159..ec75f6f2 100644 --- a/js/class.js +++ b/js/class.js @@ -90,4 +90,9 @@ function cloneObject(obj) { } /*************** DO NOT EDIT THE LINE BELOW ***************/ -if (typeof module !== "undefined") { module.exports = Class; } +if (typeof module !== "undefined") { + module.exports = Class; + module.exports._test = { + cloneObject: cloneObject + } +} diff --git a/js/module.js b/js/module.js index 0d51e559..413efa46 100644 --- a/js/module.js +++ b/js/module.js @@ -194,7 +194,7 @@ var Module = Class.extend({ * return string - File path. */ file: function (file) { - return this.data.path + "/" + file; + return (this.data.path + "/" + file).replace("//", "/"); }, /* loadStyles() diff --git a/js/server.js b/js/server.js index 78aac2fe..fbc51cbc 100644 --- a/js/server.js +++ b/js/server.js @@ -13,6 +13,7 @@ var path = require("path"); var ipfilter = require("express-ipfilter").IpFilter; var fs = require("fs"); var helmet = require("helmet"); +var Utils = require(__dirname + "/utils.js"); var Server = function(config, callback) { @@ -26,7 +27,7 @@ var Server = function(config, callback) { server.listen(port, config.address ? config.address : null); if (config.ipWhitelist instanceof Array && config.ipWhitelist.length == 0) { - console.info("You're using a full whitelist configuration to allow for all IPs") + console.info(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs")) } app.use(function(req, res, next) { diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 32b944b0..ad3be8ce 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -67,30 +67,7 @@ Module.register("calendar", { Log.log("Starting module: " + this.name); // Set locale. - moment.locale(config.language); - - switch (config.timeFormat) { - case 12: { - moment.updateLocale(config.language, { - longDateFormat: { - LT: "h:mm A" - } - }); - break; - } - case 24: { - moment.updateLocale(config.language, { - longDateFormat: { - LT: "HH:mm" - } - }); - break; - } - // If config.timeFormat was not given (or has invalid format) default to locale default - default: { - break; - } - } + moment.updateLocale(config.language, this.getLocaleSpecification(config.timeFormat)); for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; @@ -155,20 +132,6 @@ Module.register("calendar", { for (var e in events) { var event = events[e]; - - var excluded = false; - for (var f in this.config.excludedEvents) { - var filter = this.config.excludedEvents[f]; - if (event.title.toLowerCase().includes(filter.toLowerCase())) { - excluded = true; - break; - } - } - - if (excluded) { - continue; - } - var eventWrapper = document.createElement("tr"); if (this.config.colored) { @@ -322,6 +285,31 @@ Module.register("calendar", { return wrapper; }, + /** + * This function accepts a number (either 12 or 24) and returns a moment.js LocaleSpecification with the + * corresponding timeformat to be used in the calendar display. If no number is given (or otherwise invalid input) + * it will a localeSpecification object with the system locale time format. + * + * @param {number} timeFormat Specifies either 12 or 24 hour time format + * @returns {moment.LocaleSpecification} + */ + getLocaleSpecification: function(timeFormat) { + switch (timeFormat) { + case 12: { + return { longDateFormat: {LT: "h:mm A"} }; + break; + } + case 24: { + return { longDateFormat: {LT: "HH:mm"} }; + break; + } + default: { + return { longDateFormat: {LT: moment.localeData().longDateFormat("LT")} }; + break; + } + } + }, + /* hasCalendarURL(url) * Check if this config contains the calendar url. * @@ -368,7 +356,7 @@ Module.register("calendar", { return a.startDate - b.startDate; }); - return events.slice(0, this.config.maximumEntries); + return events; }, /* createEventList(url) @@ -379,6 +367,7 @@ Module.register("calendar", { addCalendar: function (url, auth, calendarConfig) { this.sendSocketNotification("ADD_CALENDAR", { url: url, + excludedEvents: calendarConfig.excludedEvents || this.config.excludedEvents, maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries, maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays, fetchInterval: this.config.fetchInterval, @@ -439,25 +428,27 @@ Module.register("calendar", { return defaultValue; }, - /* shorten(string, maxLength) - * Shortens a string if it's longer than maxLength. - * Adds an ellipsis to the end. - * - * argument string string - The string to shorten. - * argument maxLength number - The max length of the string. - * argument wrapEvents - Wrap the text after the line has reached maxLength - * - * return string - The shortened string. + /** + * Shortens a string if it's longer than maxLength and add a ellipsis to the end + * + * @param {string} string Text string to shorten + * @param {number} maxLength The max length of the string + * @param {boolean} wrapEvents Wrap the text after the line has reached maxLength + * @returns {string} The shortened string */ shorten: function (string, maxLength, wrapEvents) { - if (wrapEvents) { + if (typeof string !== "string") { + return ""; + } + + if (wrapEvents === true) { var temp = ""; var currentLine = ""; var words = string.split(" "); for (var i = 0; i < words.length; i++) { var word = words[i]; - if (currentLine.length + word.length < 25 - 1) { // max - 1 to account for a space + if (currentLine.length + word.length < (typeof maxLength === "number" ? maxLength : 25) - 1) { // max - 1 to account for a space currentLine += (word + " "); } else { if (currentLine.length > 0) { @@ -469,12 +460,12 @@ Module.register("calendar", { } } - return temp + currentLine; + return (temp + currentLine).trim(); } else { - if (string.length > maxLength) { - return string.slice(0, maxLength) + "…"; + if (maxLength && typeof maxLength === "number" && string.length > maxLength) { + return string.trim().slice(0, maxLength) + "…"; } else { - return string; + return string.trim(); } } }, diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 9655f21e..12495f78 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -8,7 +8,7 @@ var ical = require("./vendor/ical.js"); var moment = require("moment"); -var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumberOfDays, auth) { +var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth) { var self = this; var reloadTimer = null; @@ -113,6 +113,19 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe title = event.description; } + var excluded = false; + for (var f in excludedEvents) { + var filter = excludedEvents[f]; + if (title.toLowerCase().includes(filter.toLowerCase())) { + excluded = true; + break; + } + } + + if (excluded) { + continue; + } + var location = event.location || false; var geo = event.geo || false; var description = event.description || false; diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index 90c286c8..25e7f1f7 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -24,7 +24,7 @@ module.exports = NodeHelper.create({ socketNotificationReceived: function(notification, payload) { if (notification === "ADD_CALENDAR") { //console.log('ADD_CALENDAR: '); - this.createFetcher(payload.url, payload.fetchInterval, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth); + this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth); } }, @@ -36,7 +36,7 @@ module.exports = NodeHelper.create({ * attribute reloadInterval number - Reload interval in milliseconds. */ - createFetcher: function(url, fetchInterval, maximumEntries, maximumNumberOfDays, auth) { + createFetcher: function(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth) { var self = this; if (!validUrl.isUri(url)) { @@ -47,7 +47,7 @@ module.exports = NodeHelper.create({ var fetcher; if (typeof self.fetchers[url] === "undefined") { console.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval); - fetcher = new CalendarFetcher(url, fetchInterval, maximumEntries, maximumNumberOfDays, auth); + fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth); fetcher.onReceive(function(fetcher) { //console.log('Broadcast events.'); diff --git a/modules/default/currentweather/currentweather.js b/modules/default/currentweather/currentweather.js index f56dbde1..95c9a3ad 100644 --- a/modules/default/currentweather/currentweather.js +++ b/modules/default/currentweather/currentweather.js @@ -469,7 +469,7 @@ Module.register("currentweather",{ * * argument temperature number - Temperature. * - * return number - Rounded Temperature. + * return string - Rounded Temperature. */ roundValue: function(temperature) { var decimals = this.config.roundTemp ? 0 : 1; diff --git a/modules/default/weatherforecast/weatherforecast.js b/modules/default/weatherforecast/weatherforecast.js index aab3aa15..1972fac0 100644 --- a/modules/default/weatherforecast/weatherforecast.js +++ b/modules/default/weatherforecast/weatherforecast.js @@ -358,7 +358,7 @@ Module.register("weatherforecast",{ * * argument temperature number - Temperature. * - * return number - Rounded Temperature. + * return string - Rounded Temperature. */ roundValue: function(temperature) { var decimals = this.config.roundTemp ? 0 : 1; diff --git a/package.json b/package.json index fe64cc41..1fb21a9d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "start": "sh run-start.sh", "install": "cd vendor && npm install", - "postinstall": "sh installers/postinstall/postinstall.sh", + "install-fonts": "cd fonts && npm install", + "postinstall": "sh installers/postinstall/postinstall.sh && npm run install-fonts", "test": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests --recursive", "test:unit": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/unit --recursive", "test:e2e": "NODE_ENV=test ./node_modules/mocha/bin/mocha tests/e2e --recursive", @@ -44,8 +45,8 @@ "http-auth": "^3.1.3", "jshint": "^2.9.4", "mocha": "^3.4.2", - "spectron": "^3.6.4", - "stylelint": "^7.11.0", + "stylelint": "^8.0.0", + "spectron": "3.6.x", "stylelint-config-standard": "latest", "time-grunt": "latest" }, diff --git a/tests/configs/modules/clock/es/clock_showWeek.js b/tests/configs/modules/clock/es/clock_showWeek.js new file mode 100644 index 00000000..29550f04 --- /dev/null +++ b/tests/configs/modules/clock/es/clock_showWeek.js @@ -0,0 +1,38 @@ + +/* Magic Mirror + * + * Test config for default clock module + * Language es for showWeek feature + * + * By Rodrigo Ramírez Norambuena + * https://rodrigoramirez.com + * + * MIT Licensed. + */ + +var config = { + port: 8080, + ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], + + language: "es", + timeFormat: 12, + units: "metric", + electronOptions: { + webPreferences: { + nodeIntegration: true, + }, + }, + + modules: [ + { + module: "clock", + position: "middle_center", + config: { + showWeek: true + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") {module.exports = config;} diff --git a/tests/e2e/env_spec.js b/tests/e2e/env_spec.js index 50be0825..9454b92e 100644 --- a/tests/e2e/env_spec.js +++ b/tests/e2e/env_spec.js @@ -50,7 +50,7 @@ describe("Electron app environment", function() { .should.eventually.have.property("height") .and.be.above(0) .browserWindow.getTitle() - .should.eventually.equal("Magic Mirror"); + .should.eventually.equal("MagicMirror²"); }); it("get request from http://localhost:8080 should return 200", function(done) { diff --git a/tests/e2e/modules/calendar_spec.js b/tests/e2e/modules/calendar_spec.js index a1fe8503..e989cb17 100644 --- a/tests/e2e/modules/calendar_spec.js +++ b/tests/e2e/modules/calendar_spec.js @@ -72,7 +72,7 @@ describe("Calendar module", function() { }); }); - describe("Basic auth backward compatibilty configuration", function() { + describe("Basic auth backward compatibilty configuration: DEPRECATED", function() { before(function() { serverBasicAuth.listen(8012); // Set config sample for use in test diff --git a/tests/e2e/modules/clock_es_spec.js b/tests/e2e/modules/clock_es_spec.js index 5f17fd9d..455f3bed 100644 --- a/tests/e2e/modules/clock_es_spec.js +++ b/tests/e2e/modules/clock_es_spec.js @@ -73,4 +73,18 @@ describe("Clock set to spanish language module", function() { return app.client.waitUntilWindowLoaded().getText(".clock .time").should.eventually.match(timeRegex); }); }); + + describe("with showWeek config enabled", function() { + before(function() { + // Set config sample for use in test + process.env.MM_CONFIG_FILE = "tests/configs/modules/clock/es/clock_showWeek.js"; + }); + + it("shows week with correct format", function() { + const weekRegex = /^Semana [0-9]{1,2}$/; + return app.client.waitUntilWindowLoaded() + .getText(".clock .week").should.eventually.match(weekRegex); + }); + }); + }); diff --git a/tests/e2e/vendor_spec.js b/tests/e2e/vendor_spec.js index 5d9ba603..0d9751f1 100644 --- a/tests/e2e/vendor_spec.js +++ b/tests/e2e/vendor_spec.js @@ -6,21 +6,24 @@ const expect = require("chai").expect; const describe = global.describe; const it = global.it; -const beforeEach = global.beforeEach; -const afterEach = global.afterEach; +const before = global.before; +const after = global.after; describe("Vendors", function () { + + return; // Test still getting failed in Travis + helpers.setupTimeout(this); var app = null; - beforeEach(function () { + before(function () { return helpers.startApplication({ args: ["js/electron.js"] }).then(function (startedApp) { app = startedApp; }) }); - afterEach(function () { + after(function () { return helpers.stopApplication(app); }); diff --git a/tests/unit/functions/calendar_spec.js b/tests/unit/functions/calendar_spec.js index 2c7f62f8..d4035f33 100644 --- a/tests/unit/functions/calendar_spec.js +++ b/tests/unit/functions/calendar_spec.js @@ -1,9 +1,6 @@ -var fs = require("fs"); -var path = require("path"); -var chai = require("chai"); -var expect = chai.expect; -var vm = require("vm"); +const expect = require("chai").expect; +global.moment = require("moment"); describe("Functions into modules/default/calendar/calendar.js", function() { @@ -14,8 +11,10 @@ describe("Functions into modules/default/calendar/calendar.js", function() { Module.definitions[name] = moduleDefinition; }; - // load calendar.js - require("../../../modules/default/calendar/calendar.js"); + before(function() { + // load calendar.js + require("../../../modules/default/calendar/calendar.js"); + }); describe("capFirst", function() { words = { @@ -27,10 +26,103 @@ describe("Functions into modules/default/calendar/calendar.js", function() { }; Object.keys(words).forEach(word => { - it(`for ${word} should return ${words[word]}`, function() { + it(`for '${word}' should return '${words[word]}'`, function() { expect(Module.definitions.calendar.capFirst(word)).to.equal(words[word]); }); }); }); + + describe("getLocaleSpecification", function() { + it("Should return a valid moment.LocaleSpecification for a 12-hour format", function() { + expect(Module.definitions.calendar.getLocaleSpecification(12)).to.deep.equal({ longDateFormat: {LT: "h:mm A"} }); + }); + + it("Should return a valid moment.LocaleSpecification for a 24-hour format", function() { + expect(Module.definitions.calendar.getLocaleSpecification(24)).to.deep.equal({ longDateFormat: {LT: "HH:mm"} }); + }); + + it("Should return the current system locale when called without timeFormat number", function() { + expect(Module.definitions.calendar.getLocaleSpecification()).to.deep.equal({ longDateFormat: {LT: moment.localeData().longDateFormat("LT")} } ); + }); + + it("Should return a 12-hour longDateFormat when using the 'en' locale", function() { + var localeBackup = moment.locale(); + moment.locale("en"); + expect(Module.definitions.calendar.getLocaleSpecification()).to.deep.equal({ longDateFormat: {LT: "h:mm A"} }); + moment.locale(localeBackup); + }); + + it("Should return a 12-hour longDateFormat when using the 'au' locale", function() { + var localeBackup = moment.locale(); + moment.locale("au"); + expect(Module.definitions.calendar.getLocaleSpecification()).to.deep.equal({ longDateFormat: {LT: "h:mm A"} }); + moment.locale(localeBackup); + }); + + it("Should return a 12-hour longDateFormat when using the 'eg' locale", function() { + var localeBackup = moment.locale(); + moment.locale("eg"); + expect(Module.definitions.calendar.getLocaleSpecification()).to.deep.equal({ longDateFormat: {LT: "h:mm A"} }); + moment.locale(localeBackup); + }); + + it("Should return a 24-hour longDateFormat when using the 'nl' locale", function() { + var localeBackup = moment.locale(); + moment.locale("nl"); + expect(Module.definitions.calendar.getLocaleSpecification()).to.deep.equal({ longDateFormat: {LT: "HH:mm"} }); + moment.locale(localeBackup); + }); + + it("Should return a 24-hour longDateFormat when using the 'fr' locale", function() { + var localeBackup = moment.locale(); + moment.locale("fr"); + expect(Module.definitions.calendar.getLocaleSpecification()).to.deep.equal({ longDateFormat: {LT: "HH:mm"} }); + moment.locale(localeBackup); + }); + + it("Should return a 24-hour longDateFormat when using the 'uk' locale", function() { + var localeBackup = moment.locale(); + moment.locale("uk"); + expect(Module.definitions.calendar.getLocaleSpecification()).to.deep.equal({ longDateFormat: {LT: "HH:mm"} }); + moment.locale(localeBackup); + }); + }); + + describe("shorten", function() { + strings = { + " String with whitespace at the beginning that needs trimming" : { length: 16, return: "String with whit…" }, + "long string that needs shortening": { length: 16, return: "long string that…" }, + "short string": { length: 16, return: "short string" }, + "long string with no maxLength defined": { return: "long string with no maxLength defined" }, + }; + + Object.keys(strings).forEach(string => { + it(`for '${string}' should return '${strings[string].return}'`, function() { + expect(Module.definitions.calendar.shorten(string, strings[string].length)).to.equal(strings[string].return); + }); + }); + + it("should return an empty string if shorten is called with a non-string", function () { + expect(Module.definitions.calendar.shorten(100)).to.equal(""); + }); + + it("should not shorten the string if shorten is called with a non-number maxLength", function () { + expect(Module.definitions.calendar.shorten("This is a test string", "This is not a number")).to.equal("This is a test string"); + }); + + it("should wrap the string instead of shorten it if shorten is called with wrapEvents = true (with maxLength defined as 20)", function () { + expect(Module.definitions.calendar.shorten( + "This is a wrapEvent test. Should wrap the string instead of shorten it if called with wrapEvent = true", + 20, + true)).to.equal("This is a
wrapEvent test. Should wrap
the string instead of
shorten it if called with
wrapEvent = true"); + }); + + it("should wrap the string instead of shorten it if shorten is called with wrapEvents = true (without maxLength defined, default 25)", function () { + expect(Module.definitions.calendar.shorten( + "This is a wrapEvent test. Should wrap the string instead of shorten it if called with wrapEvent = true", + undefined, + true)).to.equal("This is a wrapEvent
test. Should wrap the string
instead of shorten it if called
with wrapEvent = true"); + }); + }); }); diff --git a/tests/unit/functions/class_spec.js b/tests/unit/functions/class_spec.js new file mode 100644 index 00000000..e2e6d521 --- /dev/null +++ b/tests/unit/functions/class_spec.js @@ -0,0 +1,51 @@ +var chai = require("chai"); +var expect = chai.expect; +var jsClass = require("../../../js/class.js"); + +describe("File js/class", function() { + describe("Test function cloneObject", function() { + var cloneObject = jsClass._test.cloneObject; + + it("should be return equals object", function() { + var expected = {name: "Rodrigo", web: "https://rodrigoramirez.com", project: "MagicMirror"}; + var obj = {}; + obj = cloneObject(expected); + expect(expected).to.deep.equal(obj); + }); + + it("should be return equals int", function() { + var expected = 1; + var obj = {}; + obj = cloneObject(expected); + expect(expected).to.equal(obj); + }); + + it("should be return equals string", function() { + var expected = "Perfect stranger"; + var obj = {}; + obj = cloneObject(expected); + expect(expected).to.equal(obj); + }); + + it("should be return equals undefined", function() { + var expected = undefined; + var obj = {}; + obj = cloneObject(expected); + expect(undefined).to.equal(obj); + }); + + // CoverageME + /* + context("Test lockstring code", function() { + it("should be return equals object", function() { + var expected = {name: "Module", lockStrings: "stringLock"}; + var obj = {}; + obj = cloneObject(expected); + expect(expected).to.deep.equal(obj); + }); + }); + */ + + }); +}); + diff --git a/tests/unit/functions/currentweather_spec.js b/tests/unit/functions/currentweather_spec.js new file mode 100644 index 00000000..18b52c81 --- /dev/null +++ b/tests/unit/functions/currentweather_spec.js @@ -0,0 +1,78 @@ +var fs = require("fs"); +var path = require("path"); +var chai = require("chai"); +var expect = chai.expect; +var vm = require("vm"); + + +describe("Functions module currentweather", function() { + + + // Fake for use by currentweather.js + Module = {}; + config = {}; + Module.definitions = {}; + Module.register = function (name, moduleDefinition) { + Module.definitions[name] = moduleDefinition; + }; + + + before(function(){ + require("../../../modules/default/currentweather/currentweather.js"); + Module.definitions.currentweather.config = {}; + }); + + describe("roundValue", function() { + + describe("this.config.roundTemp is true", function() { + before(function(){ + Module.definitions.currentweather.config.roundTemp = true; + }); + + var values = [ + // index 0 value + // index 1 expect + [1 , "1"], + [1.0 , "1"], + [1.02 , "1"], + [10.12 , "10"], + [2.0 , "2"], + ["2.12" , "2"], + [10.1 , "10"] + ] + + values.forEach(value => { + it(`for ${value[0]} should be return ${value[1]}`, function() { + expect(Module.definitions.currentweather.roundValue(value[0])).to.equal(value[1]); + }); + }); + }); + + + describe("this.config.roundTemp is false", function() { + + before(function(){ + Module.definitions.currentweather.config.roundTemp = false; + }); + + var values = [ + // index 0 value + // index 1 expect + [1 , "1.0"], + [1.0 , "1.0"], + [1.02 , "1.0"], + [10.12 , "10.1"], + [2.0 , "2.0"], + ["2.12" , "2.1"], + [10.1 , "10.1"], + [10.10 , "10.1"] + ] + + values.forEach(value => { + it(`for ${value[0]} should be return ${value[1]}`, function() { + expect(Module.definitions.currentweather.roundValue(value[0])).to.equal(value[1]); + }); + }); + }); + }); +}); diff --git a/tests/unit/functions/newsfeed_spec.js b/tests/unit/functions/newsfeed_spec.js new file mode 100644 index 00000000..583d696a --- /dev/null +++ b/tests/unit/functions/newsfeed_spec.js @@ -0,0 +1,37 @@ +var fs = require("fs"); +var path = require("path"); +var chai = require("chai"); +var expect = chai.expect; +var vm = require("vm"); + + +describe("Functions into modules/default/newsfeed/newsfeed.js", function() { + + Module = {} + Module.definitions = {}; + Module.register = function (name, moduleDefinition) { + Module.definitions[name] = moduleDefinition; + }; + + // load newsfeed.js + require("../../../modules/default/newsfeed/newsfeed.js"); + + describe("capitalizeFirstLetter", function() { + words = { + "rodrigo": "Rodrigo", + "123m": "123m", + "magic mirror": "Magic mirror", + ",a": ",a", + "ñandú": "Ñandú", + ".!": ".!" + }; + + Object.keys(words).forEach(word => { + it(`for ${word} should return ${words[word]}`, function() { + expect(Module.definitions.newsfeed.capitalizeFirstLetter(word)).to.equal(words[word]); + }); + }); + }); + +}); +