diff --git a/.travis.yml b/.travis.yml index 36a068a2..c473d22b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,14 @@ sudo: required +dist: xenial language: node_js -cache: - directories: - - node_modules notifications: email: false node_js: - '10' services: - xvfb +addons: + chrome: stable before_script: - npm prune script: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..1d9e7361 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at dlotts@knightrider.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/README.es_MX.md b/README.es_MX.md index 96b9590c..9828f913 100644 --- a/README.es_MX.md +++ b/README.es_MX.md @@ -102,6 +102,16 @@ Utiliza las clases `row` y `col` de bootstrap flex para el acomodo del component Si el contenedor padre no es lo suficientemente ancho (mayor a 340px) el diseño de la fila y columna que contiene el componente puede que no se muestre de manera atractiva. Otros lenguajes/locales es probable que requieran un contenedor un poco mas ancho para poder mostrar apropiadamente el contenido. +## End-to-End (e2e) testing with protractor + +**Translation Pull request needed for this section** + +The user interactions with a date-time picker make it difficult to write e2e tests that exactly replicate the users interaction with the picker. + +Fortunately, this repository contains a file you can use in your e2e tests to cause the date/time picker to select any specified date. + +See [./e2e/src/dl-date-time-picker-protractor.ts](./e2e/src/dl-date-time-picker-protractor.ts) for details. + ## Configuración Utiliza el [generador de configuración automatizado](https://stackblitz.com/github/dalelotts/angular-bootstrap-datetimepicker-demo) (por favor hazme saber si no funciona para tu caso!), o ve a [https://dalelotts.github.io/angular-bootstrap-datetimepicker/](https://dalelotts.github.io/angular-bootstrap-datetimepicker/) @@ -229,13 +239,5 @@ angular-bootstrap-datetimepicker fué liberada con la licencia MIT y copyright 2 La licencia completa de angular-bootstrap-datetimepicker se encuentra [en el repositorio del proyecto](LICENSE) para más información. -## Donativos -Puedes apoyar este proyecto y otros relizados por Dale Lotts por medio de [gittip][gittip-dalelotts]. - -[![Apoya via Gittip][gittip-badge]][gittip-dalelotts] - -[gittip-badge]: https://rawgithub.com/twolfson/gittip-badge/master/dist/gittip.png -[gittip-dalelotts]: https://www.gittip.com/dalelotts/ - [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat [license-url]: LICENSE diff --git a/README.md b/README.md index 07c20b32..905a5c7b 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,14 @@ It uses bootstrap's flex `row` and `col` classes to layout the date/time picker If the parent container is too narrow (less than 340px in english), the row and column layout may wrap in ways that are not attractive. Other languages/locals may require a wider container to fit the contents. +## End-to-End (e2e) testing with protractor + +The user interactions with a date-time picker make it difficult to write e2e tests that exactly replicate the users interaction with the picker. + +Fortunately, this repository contains a file you can use in your e2e tests to cause the date/time picker to select any specified date. + +See [./e2e/src/dl-date-time-picker-protractor.ts](./e2e/src/dl-date-time-picker-protractor.ts) for details. + ## Configuration Use the [automated configuration generator](https://stackblitz.com/github/dalelotts/angular-bootstrap-datetimepicker-demo) (please let me know if it does not work for your use case!), @@ -239,13 +247,5 @@ angular-bootstrap-datetimepicker is released under the MIT license and is copyri The full angular-bootstrap-datetimepicker license is located [in the project repository](LICENSE) for more information. -## Donating -Support this project and other work by Dale Lotts via [gittip][gittip-dalelotts]. - -[![Support via Gittip][gittip-badge]][gittip-dalelotts] - -[gittip-badge]: https://rawgithub.com/twolfson/gittip-badge/master/dist/gittip.png -[gittip-dalelotts]: https://www.gittip.com/dalelotts/ - [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat [license-url]: LICENSE diff --git a/e2e/src/app.e2e-spec.ts b/e2e/src/app.e2e-spec.ts index b0274545..22ed4683 100644 --- a/e2e/src/app.e2e-spec.ts +++ b/e2e/src/app.e2e-spec.ts @@ -1,14 +1,22 @@ -import { AppPage } from './app.po'; +import {AppPage} from './app.po'; +import pickTime from './dl-date-time-picker-protractor'; +import moment = require('moment'); describe('workspace-project App', () => { let page: AppPage; beforeEach(() => { page = new AppPage(); + return page.navigateTo(); }); - it('should display welcome message', () => { - page.navigateTo(); - expect(page.getParagraphText()).toEqual('Welcome to angular-bootstrap-datetimepicker!'); + it('Picking time updates Selected Date:', async () => { + const todayAtMidnight = moment('2003-11-07T21:32:17.800Z'); + const expectedDate = new Date('2003-11-07T21:30:00.000Z').toString(); + + await pickTime(page.getDateTimePicker(), todayAtMidnight.valueOf()); + + const selectedDate = page.getSelectedDate().getText(); + expect(selectedDate).toBe(`Selected Date: ${expectedDate}`); }); }); diff --git a/e2e/src/app.po.ts b/e2e/src/app.po.ts index 82ea75ba..56a1eaf4 100644 --- a/e2e/src/app.po.ts +++ b/e2e/src/app.po.ts @@ -8,4 +8,12 @@ export class AppPage { getParagraphText() { return element(by.css('app-root h1')).getText(); } + + getDateTimePicker() { + return element(by.tagName('dl-date-time-picker')); + } + + getSelectedDate() { + return element(by.id('selectedDate')); + } } diff --git a/e2e/src/dl-date-time-picker-protractor.ts b/e2e/src/dl-date-time-picker-protractor.ts new file mode 100644 index 00000000..02cad33f --- /dev/null +++ b/e2e/src/dl-date-time-picker-protractor.ts @@ -0,0 +1,83 @@ +import {by, ElementArrayFinder, ElementFinder} from 'protractor'; + +/** + * This file is an example of how you can implement automated end-to-end tests for the + * date/time picker component. + * + * The overall strategy here is to use the `dl-abdtp-value` attributes, which contain numeric date values, + * to determine which buttons to click on the picker in order to select a target dates. + */ + +/** + * Clicks the nearest date button with a value less than or equal to the specified time. + * @param dateButtons + * the possible date buttons. + * @param time + * the desired selected time. + */ + +export function clickNearestDateButton(dateButtons: ElementArrayFinder, time: number) { + return dateButtons + .filter(button => button.getAttribute('dl-abdtp-value').then(buttonValue => Number(buttonValue) <= time)) + .last().click(); +} + +/** + * Have the dateTimePicker select the best possible value that is less than or equal to the specified time. + * based on the current configuration of the dateTimePicker. + * + * This function will `not` select a time value `greater than` the specified time value. + * + * Additionally, this function depends on `ng-reflect-*` attributes which will never exist in a production build. + * + * @param dateTimePicker + * the target dateTimePicker + * + * @param time + * the desired selected time. + */ +async function pickTime(dateTimePicker: ElementFinder, time: number) { + const dateButtons = dateTimePicker.all(by.className('dl-abdtp-date-button')); + const leftButton = dateTimePicker.element(by.className('dl-abdtp-left-button')); + const rightButton = dateTimePicker.element(by.className('dl-abdtp-right-button')); + const upButton = dateTimePicker.element(by.className('dl-abdtp-up-button')); + const viewAttributeName = 'data-dl-abdtp-view'; + const viewElement = dateTimePicker.element(by.css(`[${viewAttributeName}]`)); + + const maxView = await dateTimePicker.getAttribute('ng-reflect-max-view'); + const minView = await dateTimePicker.getAttribute('ng-reflect-min-view'); + + let currentView = await viewElement.getAttribute(viewAttributeName); + + // Go up to the max view in order to drill down by selecting the nearest button value. + while (maxView !== currentView) { + await upButton.click(); + currentView = await viewElement.getAttribute(viewAttributeName); + } + + let firstButtonValue = await dateButtons.first().getAttribute('dl-abdtp-value'); + + // This left and right navigation to find the target date range assumes that earlier times are to the left. + // This is true for the default implementation but may not be true for all implementations. + + while (Number(firstButtonValue) > time) { + await leftButton.click(); + firstButtonValue = await dateButtons.first().getAttribute('dl-abdtp-value'); + } + + let lastButtonValue = await dateButtons.last().getAttribute('dl-abdtp-value'); + + while (Number(lastButtonValue) <= time) { + await rightButton.click(); + lastButtonValue = await dateButtons.last().getAttribute('dl-abdtp-value'); + } + + while (minView !== currentView) { + await clickNearestDateButton(dateButtons, time); + currentView = await viewElement.getAttribute(viewAttributeName); + } + + return clickNearestDateButton(dateButtons, time); +} + +export default pickTime; diff --git a/images/coverage-badge.svg b/images/coverage-badge.svg index e297156d..d12452ae 100644 --- a/images/coverage-badge.svg +++ b/images/coverage-badge.svg @@ -1,9 +1 @@ - - - - - - documentation - 95% - - +documentation95% \ No newline at end of file diff --git a/package.json b/package.json index f3f1eef9..dc9fc1ad 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,12 @@ "build:styles": "scss-bundle -c scss-bundle.config.json", "coverage:upload": "cat build/coverage/lcov.info | coveralls", "document": "compodoc --disableInternal --disablePrivate --disableLifeCycleHooks --assetsFolder screenshots -p src/tsconfig.doc.json --gaID UA-325325-19 -n \"Angular Bootstrap Date/Time Picker\"", - "e2e": "ng e2e", "lint": "ng lint", "ng": "ng", "start": "ng serve", - "test": "ng lint && ng test --watch=false --code-coverage && ng build --prod && npm run build:lib", + "test": "ng lint && ng test --watch=false --code-coverage && npm run-script test:e2e && ng build --prod && npm run build:lib", "test:tdd": "ng test", + "test:e2e": "ng e2e", "semantic-release": "semantic-release", "travis-deploy-once": "travis-deploy-once" }, diff --git a/screenshots/day.png b/screenshots/day.png index 21eb5484..3d0b68d8 100644 Binary files a/screenshots/day.png and b/screenshots/day.png differ diff --git a/screenshots/hour.png b/screenshots/hour.png index b5a1ed97..42b2a752 100644 Binary files a/screenshots/hour.png and b/screenshots/hour.png differ diff --git a/screenshots/minute.png b/screenshots/minute.png index 62088011..bbf888bc 100644 Binary files a/screenshots/minute.png and b/screenshots/minute.png differ diff --git a/screenshots/month.png b/screenshots/month.png index e7debc20..afef347c 100644 Binary files a/screenshots/month.png and b/screenshots/month.png differ diff --git a/screenshots/year.png b/screenshots/year.png index 09b09873..867af12f 100644 Binary files a/screenshots/year.png and b/screenshots/year.png differ diff --git a/src/app/app.component.html b/src/app/app.component.html index bfce1ed0..f038d020 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -79,6 +79,6 @@ [(ngModel)]="selectedDate" (change)="onCustomDateChange($event)"> -

Selected Date: {{selectedDate}}

+

Selected Date: {{selectedDate}}

diff --git a/src/lib/dl-date-time-picker/dl-date-time-picker.component.html b/src/lib/dl-date-time-picker/dl-date-time-picker.component.html index ef87c433..0cc3a343 100644 --- a/src/lib/dl-date-time-picker/dl-date-time-picker.component.html +++ b/src/lib/dl-date-time-picker/dl-date-time-picker.component.html @@ -1,12 +1,12 @@ -
+
@@ -14,23 +14,25 @@
-
{{label}}
+
{{label}}
{ diff --git a/src/lib/dl-date-time-picker/dl-model-provider-hour.ts b/src/lib/dl-date-time-picker/dl-model-provider-hour.ts index 99da9c12..7fa9b4ea 100644 --- a/src/lib/dl-date-time-picker/dl-model-provider-hour.ts +++ b/src/lib/dl-date-time-picker/dl-model-provider-hour.ts @@ -73,7 +73,7 @@ export class DlHourModelProvider implements DlModelProvider { ? selectedMilliseconds : moment(selectedMilliseconds).startOf('hour').valueOf(); - const result: DlDateTimePickerModel = { + return { viewName: 'hour', viewLabel: startDate.format('ll'), activeDate: activeValue, @@ -95,11 +95,6 @@ export class DlHourModelProvider implements DlModelProvider { rows: rowNumbers.map(rowOfHours) }; - result.leftButton.classes[`${result.leftButton.value}`] = true; - result.rightButton.classes[`${result.rightButton.value}`] = true; - - return result; - function rowOfHours(rowNumber) { const currentMoment = moment(); diff --git a/src/lib/dl-date-time-picker/dl-model-provider-minute.ts b/src/lib/dl-date-time-picker/dl-model-provider-minute.ts index d8b6349f..264dfe01 100644 --- a/src/lib/dl-date-time-picker/dl-model-provider-minute.ts +++ b/src/lib/dl-date-time-picker/dl-model-provider-minute.ts @@ -107,7 +107,7 @@ export class DlMinuteModelProvider implements DlModelProvider { return {cells: minuteSteps.slice((value * 4), (value * 4) + 4).map(rowOfMinutes)}; }); - const result: DlDateTimePickerModel = { + return { viewName: 'minute', viewLabel: startDate.format('lll'), activeDate: activeValue, @@ -129,11 +129,6 @@ export class DlMinuteModelProvider implements DlModelProvider { rows }; - result.leftButton.classes[`${result.leftButton.value}`] = true; - result.rightButton.classes[`${result.rightButton.value}`] = true; - - return result; - function rowOfMinutes(stepMinutes): { display: string; ariaLabel: string; diff --git a/src/lib/dl-date-time-picker/dl-model-provider-month.ts b/src/lib/dl-date-time-picker/dl-model-provider-month.ts index d0af7752..f3e85cca 100644 --- a/src/lib/dl-date-time-picker/dl-model-provider-month.ts +++ b/src/lib/dl-date-time-picker/dl-model-provider-month.ts @@ -73,7 +73,7 @@ export class DlMonthModelProvider implements DlModelProvider { ? selectedMilliseconds : moment(selectedMilliseconds).startOf('month').valueOf(); - const result = { + return { viewName: 'month', viewLabel: startDate.format('YYYY'), activeDate: activeValue, @@ -95,11 +95,6 @@ export class DlMonthModelProvider implements DlModelProvider { rows: rowNumbers.map(rowOfMonths) }; - result.leftButton.classes[`${result.leftButton.value}`] = true; - result.rightButton.classes[`${result.rightButton.value}`] = true; - - return result; - function rowOfMonths(rowNumber) { const currentMoment = moment(); diff --git a/src/lib/dl-date-time-picker/dl-model-provider-year.ts b/src/lib/dl-date-time-picker/dl-model-provider-year.ts index b0b8f793..13f00996 100644 --- a/src/lib/dl-date-time-picker/dl-model-provider-year.ts +++ b/src/lib/dl-date-time-picker/dl-model-provider-year.ts @@ -91,7 +91,7 @@ export class DlYearModelProvider implements DlModelProvider { ? selectedMilliseconds : moment(selectedMilliseconds).startOf('year').valueOf(); - const result: DlDateTimePickerModel = { + return { viewName: 'year', viewLabel: `${pastYear}-${futureYear}`, activeDate: activeValue, @@ -108,11 +108,6 @@ export class DlYearModelProvider implements DlModelProvider { rows: rowNumbers.map(rowOfYears.bind(this)) }; - result.leftButton.classes[`${result.leftButton.value}`] = true; - result.rightButton.classes[`${result.rightButton.value}`] = true; - - return result; - function rowOfYears(rowNumber) { const currentMoment = moment(); diff --git a/src/lib/dl-date-time-picker/specs/start-view/day-view.spec.ts b/src/lib/dl-date-time-picker/specs/start-view/day-view.spec.ts index 3d935ff0..5491807a 100644 --- a/src/lib/dl-date-time-picker/specs/start-view/day-view.spec.ts +++ b/src/lib/dl-date-time-picker/specs/start-view/day-view.spec.ts @@ -26,7 +26,7 @@ import { SPACE, UP_ARROW } from '../dispatch-events'; -import {DEC, JAN, NOV} from '../month-constants'; +import {DEC, FEB, JAN, NOV} from '../month-constants'; @Component({ template: '' @@ -108,7 +108,7 @@ describe('DlDateTimePickerComponent startView=day', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-now')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().format('D')); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('day').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('day').valueOf().toString()); }); it('should NOT contain an .dl-abdtp-now element in the previous month', () => { @@ -133,7 +133,7 @@ describe('DlDateTimePickerComponent startView=day', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-active')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().format('D')); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('day').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('day').valueOf().toString()); }); it('should contain 1 [tabindex=1] element', () => { @@ -156,7 +156,7 @@ describe('DlDateTimePickerComponent startView=day', () => { const selectedElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-selected')); expect(selectedElements.length).toBe(1); expect(selectedElements[0].nativeElement.textContent.trim()).toBe(moment().format('D')); - expect(selectedElements[0].nativeElement.classList).toContain(moment().startOf('day').valueOf().toString()); + expect(selectedElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('day').valueOf().toString()); }); }); @@ -220,7 +220,7 @@ describe('DlDateTimePickerComponent startView=day', () => { it('should contain 42 .dl-abdtp-day elements with start of day utc time as class and role of gridcell', () => { const startMoment = moment(new Date(2017, DEC, 31)); - const expectedClass = new Array(42) + const expectedValues = new Array(42) .fill(0) .map((value, index) => moment(startMoment).add(index, 'days').valueOf()); @@ -228,9 +228,9 @@ describe('DlDateTimePickerComponent startView=day', () => { expect(dayElements.length).toBe(42); dayElements.forEach((dayElement, index) => { - const key = expectedClass[index]; - const ariaLabel = moment(key).format('ll'); - expect(dayElement.nativeElement.classList).toContain(key.toString(10)); + const expectedValue = expectedValues[index]; + const ariaLabel = moment(expectedValue).format('ll'); + expect(dayElement.attributes['dl-abdtp-value']).toBe(expectedValue.toString(10), index); expect(dayElement.attributes['role']).toBe('gridcell', index); expect(dayElement.attributes['aria-label']).toBe(ariaLabel, index); }); @@ -246,9 +246,9 @@ describe('DlDateTimePickerComponent startView=day', () => { expect(leftButton.attributes['aria-label']).toBe('Go to Dec 2017'); }); - it('should have a class for previous month value on .dl-abdtp-left-button ', () => { + it('should have a dl-abdtp-value for previous month on .dl-abdtp-left-button ', () => { const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-left-button')); - expect(leftButton.nativeElement.classList).toContain(new Date(2017, DEC, 1).getTime().toString()); + expect(leftButton.attributes['dl-abdtp-value']).toBe(new Date(2017, DEC, 1).getTime().toString()); }); it('should switch to previous month value after clicking .dl-abdtp-left-button', () => { @@ -261,7 +261,7 @@ describe('DlDateTimePickerComponent startView=day', () => { const dayElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-day')); expect(dayElements[0].nativeElement.textContent.trim()).toBe('26'); - expect(dayElements[0].nativeElement.classList).toContain(new Date(2017, NOV, 26).getTime().toString()); + expect(dayElements[0].attributes['dl-abdtp-value']).toBe(new Date(2017, NOV, 26).getTime().toString()); }); it('.dl-abdtp-right-button should contain a title', () => { @@ -274,6 +274,11 @@ describe('DlDateTimePickerComponent startView=day', () => { expect(leftButton.attributes['aria-label']).toBe('Go to Feb 2018'); }); + it('should have a dl-abdtp-value for next month on .dl-abdtp-right-button ', () => { + const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-right-button')); + expect(leftButton.attributes['dl-abdtp-value']).toBe(new Date(2018, FEB, 1).getTime().toString()); + }); + it('should switch to next month value after clicking .dl-abdtp-right-button', () => { const rightButton = fixture.debugElement.query(By.css('.dl-abdtp-right-button')); rightButton.nativeElement.click(); @@ -284,7 +289,7 @@ describe('DlDateTimePickerComponent startView=day', () => { const dayElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-day')); expect(dayElements[0].nativeElement.textContent.trim()).toBe('28'); - expect(dayElements[0].nativeElement.classList).toContain(new Date(2018, JAN, 28).getTime().toString()); + expect(dayElements[0].attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 28).getTime().toString()); }); it('.dl-abdtp-up-button should contain a title', () => { diff --git a/src/lib/dl-date-time-picker/specs/start-view/hour-view.spec.ts b/src/lib/dl-date-time-picker/specs/start-view/hour-view.spec.ts index 59478f8c..1ad670d2 100644 --- a/src/lib/dl-date-time-picker/specs/start-view/hour-view.spec.ts +++ b/src/lib/dl-date-time-picker/specs/start-view/hour-view.spec.ts @@ -99,7 +99,7 @@ describe('DlDateTimePickerComponent startView=hour', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-now')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().startOf('hour').format('LT')); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('hour').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('hour').valueOf().toString()); }); it('should NOT contain an .dl-abdtp-now element in the previous day', () => { @@ -124,7 +124,7 @@ describe('DlDateTimePickerComponent startView=hour', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-active')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().startOf('hour').format('LT')); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('hour').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('hour').valueOf().toString()); }); it('should contain 1 [tabindex=1] element', () => { @@ -147,7 +147,7 @@ describe('DlDateTimePickerComponent startView=hour', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-selected')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().startOf('hour').format('LT')); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('hour').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('hour').valueOf().toString()); }); }); @@ -175,7 +175,7 @@ describe('DlDateTimePickerComponent startView=hour', () => { it('should contain 24 .dl-abdtp-hour elements with start of hour utc time as class and role of gridcell', () => { - const expectedClass = new Array(24) + const expectedValues = new Array(24) .fill(0) .map((value, index) => new Date(2018, JAN, 26, index).getTime()); @@ -183,9 +183,9 @@ describe('DlDateTimePickerComponent startView=hour', () => { expect(hourElements.length).toBe(24); hourElements.forEach((hourElement, index) => { - const key = expectedClass[index]; - const ariaLabel = moment(key).format('LLL'); - expect(hourElement.nativeElement.classList).toContain(key.toString(10)); + const expectedValue = expectedValues[index]; + const ariaLabel = moment(expectedValue).format('LLL'); + expect(hourElement.attributes['dl-abdtp-value']).toBe(expectedValue.toString(10), index); expect(hourElement.attributes['role']).toBe('gridcell', index); expect(hourElement.attributes['aria-label']).toBe(ariaLabel, index); }); @@ -196,14 +196,9 @@ describe('DlDateTimePickerComponent startView=hour', () => { expect(leftButton.attributes['title']).toBe('Go to Jan 25, 2018'); }); - it('.dl-abdtp-left-button should contain aria-label', () => { + it('should have a dl-abdtp-value attribute with the previous month value on .dl-abdtp-left-button ', () => { const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-left-button')); - expect(leftButton.attributes['aria-label']).toBe('Go to Jan 25, 2018'); - }); - - it('should have a class for previous month value on .dl-abdtp-left-button ', () => { - const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-left-button')); - expect(leftButton.nativeElement.classList).toContain(new Date(2018, JAN, 25).getTime().toString()); + expect(leftButton.attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 25).getTime().toString()); }); it('should switch to previous month value after clicking .dl-abdtp-left-button', () => { @@ -216,7 +211,7 @@ describe('DlDateTimePickerComponent startView=hour', () => { const hourElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-hour')); expect(hourElements[0].nativeElement.textContent.trim()).toBe('12:00 AM'); - expect(hourElements[0].nativeElement.classList).toContain(new Date(2018, JAN, 25).getTime().toString()); + expect(hourElements[0].attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 25).getTime().toString()); }); it('.dl-abdtp-right-button should contain a title', () => { @@ -229,9 +224,9 @@ describe('DlDateTimePickerComponent startView=hour', () => { expect(leftButton.attributes['aria-label']).toBe('Go to Jan 27, 2018'); }); - it('should have a class for previous month value on .dl-abdtp-right-button ', () => { + it('should have a dl-abdtp-value attribute with the next month value on .dl-abdtp-right-button ', () => { const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-right-button')); - expect(leftButton.nativeElement.classList).toContain(new Date(2018, JAN, 27).getTime().toString()); + expect(leftButton.attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 27).getTime().toString()); }); it('should switch to next month value after clicking .dl-abdtp-right-button', () => { @@ -244,7 +239,7 @@ describe('DlDateTimePickerComponent startView=hour', () => { const hourElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-hour')); expect(hourElements[0].nativeElement.textContent.trim()).toBe('12:00 AM'); - expect(hourElements[0].nativeElement.classList).toContain(new Date(2018, JAN, 27).getTime().toString()); + expect(hourElements[0].attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 27).getTime().toString()); }); it('.dl-abdtp-up-button should contain a title', () => { diff --git a/src/lib/dl-date-time-picker/specs/start-view/minute-view.spec.ts b/src/lib/dl-date-time-picker/specs/start-view/minute-view.spec.ts index 828f0fcc..9b81bcc6 100644 --- a/src/lib/dl-date-time-picker/specs/start-view/minute-view.spec.ts +++ b/src/lib/dl-date-time-picker/specs/start-view/minute-view.spec.ts @@ -108,7 +108,7 @@ describe('DlDateTimePickerComponent startView=minute', () => { const currentMoment = moment(minuteValues.filter((value) => value < now.valueOf()).pop()); expect(currentElements[0].nativeElement.textContent.trim()).toBe(currentMoment.format('LT')); - expect(currentElements[0].nativeElement.classList).toContain(currentMoment.valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(currentMoment.valueOf().toString()); }); it('should NOT contain an .dl-abdtp-now element in the previous hour', () => { @@ -148,7 +148,7 @@ describe('DlDateTimePickerComponent startView=minute', () => { const currentMoment = moment(minuteValues.filter((value) => value < now.valueOf()).pop()); expect(currentElements[0].nativeElement.textContent.trim()).toBe(currentMoment.format('LT')); - expect(currentElements[0].nativeElement.classList).toContain(currentMoment.valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(currentMoment.valueOf().toString()); }); it('should contain 1 .dl-abdtp-selected element for the current minute', () => { @@ -168,7 +168,7 @@ describe('DlDateTimePickerComponent startView=minute', () => { fixture.detectChanges(); expect(currentElements[0].nativeElement.textContent.trim()).toBe(currentMoment.format('LT')); - expect(currentElements[0].nativeElement.classList).toContain(currentMoment.valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(currentMoment.valueOf().toString()); }); }); @@ -195,7 +195,7 @@ describe('DlDateTimePickerComponent startView=minute', () => { }); it('should contain 12 .dl-abdtp-minute elements with start of minute utc time as class and role of gridcell', () => { - const expectedClass = new Array(12) + const expectedValues = new Array(12) .fill(0) .map((value, index) => new Date(2018, JAN, 26, 15, 5 * index).getTime()); @@ -203,9 +203,9 @@ describe('DlDateTimePickerComponent startView=minute', () => { expect(minuteElements.length).toBe(12); minuteElements.forEach((minuteElement, index) => { - const key = expectedClass[index]; - const ariaLabel = moment(key).format('LLL'); - expect(minuteElement.nativeElement.classList).toContain(key.toString(10)); + const expectedValue = expectedValues[index]; + const ariaLabel = moment(expectedValue).format('LLL'); + expect(minuteElement.attributes['dl-abdtp-value']).toBe(expectedValue.toString(10), index); expect(minuteElement.attributes['role']).toBe('gridcell', index); expect(minuteElement.attributes['aria-label']).toBe(ariaLabel, index); }); @@ -221,9 +221,9 @@ describe('DlDateTimePickerComponent startView=minute', () => { expect(leftButton.attributes['aria-label']).toBe('Go to Jan 26, 2018 2:00 PM'); }); - it('should have a class for previous hour value on .dl-abdtp-left-button ', () => { + it('should have a dl-abdtp-value attribute for previous hour value on .dl-abdtp-left-button ', () => { const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-left-button')); - expect(leftButton.nativeElement.classList).toContain(new Date(2018, JAN, 26, 14).getTime().toString()); + expect(leftButton.attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 26, 14).getTime().toString()); }); it('should switch to previous hour value after clicking .dl-abdtp-left-button', () => { @@ -236,7 +236,7 @@ describe('DlDateTimePickerComponent startView=minute', () => { const minuteElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-minute')); expect(minuteElements[0].nativeElement.textContent.trim()).toBe('2:00 PM'); - expect(minuteElements[0].nativeElement.classList).toContain(new Date(2018, JAN, 26, 14).getTime().toString()); + expect(minuteElements[0].attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 26, 14).getTime().toString()); }); it('.dl-abdtp-right-button should contain a title', () => { @@ -249,9 +249,9 @@ describe('DlDateTimePickerComponent startView=minute', () => { expect(leftButton.attributes['aria-label']).toBe('Go to Jan 26, 2018 4:00 PM'); }); - it('should have a class for next hour value on .dl-abdtp-right-button ', () => { + it('should have a dl-abdtp-value attribute with the next hour value on .dl-abdtp-right-button ', () => { const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-right-button')); - expect(leftButton.nativeElement.classList).toContain(new Date(2018, JAN, 26, 16).getTime().toString()); + expect(leftButton.attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 26, 16).getTime().toString()); }); it('should switch to next hour value after clicking .dl-abdtp-right-button', () => { @@ -264,7 +264,7 @@ describe('DlDateTimePickerComponent startView=minute', () => { const minuteElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-minute')); expect(minuteElements[0].nativeElement.textContent.trim()).toBe('4:00 PM'); - expect(minuteElements[0].nativeElement.classList).toContain(new Date(2018, JAN, 26, 16).getTime().toString()); + expect(minuteElements[0].attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 26, 16).getTime().toString()); }); it('.dl-abdtp-up-button should contain a title', () => { diff --git a/src/lib/dl-date-time-picker/specs/start-view/month-view.spec.ts b/src/lib/dl-date-time-picker/specs/start-view/month-view.spec.ts index 44109160..9e325c1d 100644 --- a/src/lib/dl-date-time-picker/specs/start-view/month-view.spec.ts +++ b/src/lib/dl-date-time-picker/specs/start-view/month-view.spec.ts @@ -97,7 +97,7 @@ describe('DlDateTimePickerComponent startView=month', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-now')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().format('MMM')); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('month').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('month').valueOf().toString()); }); it('should NOT contain an .dl-abdtp-now element in the previous year', () => { @@ -127,7 +127,7 @@ describe('DlDateTimePickerComponent startView=month', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-active')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().format('MMM')); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('month').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('month').valueOf().toString()); }); it('should contain 1 .dl-abdtp-selected element for the current month', () => { @@ -145,7 +145,7 @@ describe('DlDateTimePickerComponent startView=month', () => { const selectedElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-selected')); expect(selectedElements.length).toBe(1); expect(selectedElements[0].nativeElement.textContent.trim()).toBe(moment().format('MMM')); - expect(selectedElements[0].nativeElement.classList).toContain(moment().startOf('month').valueOf().toString()); + expect(selectedElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('month').valueOf().toString()); }); }); @@ -175,7 +175,7 @@ describe('DlDateTimePickerComponent startView=month', () => { it('should contain 12 .dl-abdtp-month elements with start of month utc time as class and role of gridcell', () => { - const expectedClass = new Array(12) + const expectedValues = new Array(12) .fill(0) .map((value, index) => new Date(2017, JAN + index, 1).getTime()); @@ -183,9 +183,9 @@ describe('DlDateTimePickerComponent startView=month', () => { expect(monthElements.length).toBe(12); monthElements.forEach((monthElement, index) => { - const key = expectedClass[index]; - const ariaLabel = moment(key).format('MMM YYYY'); - expect(monthElement.nativeElement.classList).toContain(key.toString()); + const expectedValue = expectedValues[index]; + const ariaLabel = moment(expectedValue).format('MMM YYYY'); + expect(monthElement.attributes['dl-abdtp-value']).toBe(expectedValue.toString(10), index); expect(monthElement.attributes['role']).toBe('gridcell', index); expect(monthElement.attributes['aria-label']).toBe(ariaLabel, index); }); @@ -201,9 +201,9 @@ describe('DlDateTimePickerComponent startView=month', () => { expect(leftButton.attributes['aria-label']).toBe('Go to 2016'); }); - it('should have a class for previous year value on .dl-abdtp-left-button ', () => { + it('should have a dl-abdtp-value attribute with the previous year value on .dl-abdtp-left-button ', () => { const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-left-button')); - expect(leftButton.nativeElement.classList).toContain(new Date(2016, JAN, 1).getTime().toString()); + expect(leftButton.attributes['dl-abdtp-value']).toBe(new Date(2016, JAN, 1).getTime().toString()); }); it('should switch to previous year value after clicking .dl-abdtp-left-button', () => { @@ -216,7 +216,7 @@ describe('DlDateTimePickerComponent startView=month', () => { const monthElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-month')); expect(monthElements[0].nativeElement.textContent.trim()).toBe('Jan'); - expect(monthElements[0].nativeElement.classList).toContain(new Date(2016, JAN, 1).getTime().toString()); + expect(monthElements[0].attributes['dl-abdtp-value']).toBe(new Date(2016, JAN, 1).getTime().toString()); }); it('.dl-abdtp-right-button should contain a title', () => { @@ -229,9 +229,9 @@ describe('DlDateTimePickerComponent startView=month', () => { expect(leftButton.attributes['aria-label']).toBe('Go to 2018'); }); - it('should have a class for next year value on .dl-abdtp-right-button ', () => { + it('should have a dl-abdtp-value attribute with the next year value on .dl-abdtp-right-button ', () => { const rightButton = fixture.debugElement.query(By.css('.dl-abdtp-right-button')); - expect(rightButton.nativeElement.classList).toContain(new Date(2018, JAN, 1).getTime().toString()); + expect(rightButton.attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 1).getTime().toString()); }); it('should switch to next year value after clicking .dl-abdtp-right-button', () => { @@ -244,7 +244,7 @@ describe('DlDateTimePickerComponent startView=month', () => { const monthElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-month')); expect(monthElements[0].nativeElement.textContent.trim()).toBe('Jan'); - expect(monthElements[0].nativeElement.classList).toContain(new Date(2018, JAN, 1).getTime().toString()); + expect(monthElements[0].attributes['dl-abdtp-value']).toBe(new Date(2018, JAN, 1).getTime().toString()); }); it('.dl-abdtp-up-button should contain a title', () => { diff --git a/src/lib/dl-date-time-picker/specs/start-view/year-view.spec.ts b/src/lib/dl-date-time-picker/specs/start-view/year-view.spec.ts index 8721d6b2..cb3d56a8 100644 --- a/src/lib/dl-date-time-picker/specs/start-view/year-view.spec.ts +++ b/src/lib/dl-date-time-picker/specs/start-view/year-view.spec.ts @@ -104,7 +104,7 @@ describe('DlDateTimePickerComponent', () => { const currentElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-now')); expect(currentElements.length).toBe(1); expect(currentElements[0].nativeElement.textContent.trim()).toBe(moment().year().toString()); - expect(currentElements[0].nativeElement.classList).toContain(moment().startOf('year').valueOf().toString()); + expect(currentElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('year').valueOf().toString()); }); it('should contain 1 [tabindex=1] element', () => { @@ -134,7 +134,7 @@ describe('DlDateTimePickerComponent', () => { const activeElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-active')); expect(activeElements.length).toBe(1); expect(activeElements[0].nativeElement.textContent.trim()).toBe(moment().year().toString()); - expect(activeElements[0].nativeElement.classList).toContain(moment().startOf('year').valueOf().toString()); + expect(activeElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('year').valueOf().toString()); }); it('should contain 1 .dl-abdtp-selected element for the current year', () => { @@ -152,7 +152,7 @@ describe('DlDateTimePickerComponent', () => { const selectedElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-selected')); expect(selectedElements.length).toBe(1); expect(selectedElements[0].nativeElement.textContent.trim()).toBe(moment().year().toString()); - expect(selectedElements[0].nativeElement.classList).toContain(moment().startOf('year').valueOf().toString()); + expect(selectedElements[0].attributes['dl-abdtp-value']).toBe(moment().startOf('year').valueOf().toString()); }); }); @@ -182,24 +182,24 @@ describe('DlDateTimePickerComponent', () => { // Truncate the last digit from the current year to get the start of the decade const startDecade = (Math.trunc(moment().year() / 10) * 10); - const expectedClass = new Array(10) + const expectedValues = new Array(10) .fill(0) - .map((value, index) => new Date(startDecade + index, JAN, 1).getTime().toString()); + .map((value, index) => new Date(startDecade + index, JAN, 1).getTime()); const yearElements = fixture.debugElement.queryAll(By.css('.dl-abdtp-year')); yearElements.forEach((yearElement, index) => { - const key = expectedClass[index]; - expect(yearElement.nativeElement.classList).toContain(key); + const expectedValue = expectedValues[index]; + expect(yearElement.attributes['dl-abdtp-value']).toBe(expectedValue.toString(10), index); expect(yearElement.attributes['role']).toBe('gridcell', index); expect(yearElement.attributes['aria-label']).toBeNull(); // why isn't this undefined? }); }); - it('should have a class for previous decade value on .dl-abdtp-left-button ', () => { + it('should have a dl-abdtp-value attribute with the previous decade value on .dl-abdtp-left-button ', () => { const leftButton = fixture.debugElement.query(By.css('.dl-abdtp-left-button')); const expected = new Date(2000, JAN, 1).getTime(); - expect(leftButton.nativeElement.classList).toContain(expected.toString()); + expect(leftButton.attributes['dl-abdtp-value']).toBe(expected.toString()); }); it('should switch to previous decade value after clicking .dl-abdtp-left-button', () => { @@ -214,10 +214,10 @@ describe('DlDateTimePickerComponent', () => { expect(yearElements[0].nativeElement.textContent.trim()).toBe('2000'); }); - it('should has a class for next decade on .dl-abdtp-right-button ', () => { - const rightButton = fixture.debugElement.query(By.css('.dl-abdtp-right-button')).nativeElement; + it('should has a dl-abdtp-value attribute with the next decade value on .dl-abdtp-right-button ', () => { + const rightButton = fixture.debugElement.query(By.css('.dl-abdtp-right-button')); const expected = new Date(2020, JAN, 1).getTime(); - expect(rightButton.classList).toContain(expected.toString()); + expect(rightButton.attributes['dl-abdtp-value']).toBe(expected.toString()); }); it('should switch to next decade after clicking .dl-abdtp-right-button', () => {