diff --git a/.gitignore b/.gitignore
index c9f9c9c..9203ebc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,5 @@ examples/js
*.njsproj
*.sln
+# Testing
+cypress/screenshots
diff --git a/cypress/.eslintrc b/cypress/.eslintrc
new file mode 100644
index 0000000..37d28b0
--- /dev/null
+++ b/cypress/.eslintrc
@@ -0,0 +1,8 @@
+{
+ "plugins": [
+ "cypress"
+ ],
+ "env": {
+ "cypress/globals": true
+ }
+}
diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json
new file mode 100644
index 0000000..da18d93
--- /dev/null
+++ b/cypress/fixtures/example.json
@@ -0,0 +1,5 @@
+{
+ "name": "Using fixtures to represent data",
+ "email": "hello@cypress.io",
+ "body": "Fixtures are a great way to mock data for responses to routes"
+}
\ No newline at end of file
diff --git a/cypress/fixtures/profile.json b/cypress/fixtures/profile.json
new file mode 100644
index 0000000..b6c355c
--- /dev/null
+++ b/cypress/fixtures/profile.json
@@ -0,0 +1,5 @@
+{
+ "id": 8739,
+ "name": "Jane",
+ "email": "jane@example.com"
+}
\ No newline at end of file
diff --git a/cypress/fixtures/users.json b/cypress/fixtures/users.json
new file mode 100644
index 0000000..79b699a
--- /dev/null
+++ b/cypress/fixtures/users.json
@@ -0,0 +1,232 @@
+[
+ {
+ "id": 1,
+ "name": "Leanne Graham",
+ "username": "Bret",
+ "email": "Sincere@april.biz",
+ "address": {
+ "street": "Kulas Light",
+ "suite": "Apt. 556",
+ "city": "Gwenborough",
+ "zipcode": "92998-3874",
+ "geo": {
+ "lat": "-37.3159",
+ "lng": "81.1496"
+ }
+ },
+ "phone": "1-770-736-8031 x56442",
+ "website": "hildegard.org",
+ "company": {
+ "name": "Romaguera-Crona",
+ "catchPhrase": "Multi-layered client-server neural-net",
+ "bs": "harness real-time e-markets"
+ }
+ },
+ {
+ "id": 2,
+ "name": "Ervin Howell",
+ "username": "Antonette",
+ "email": "Shanna@melissa.tv",
+ "address": {
+ "street": "Victor Plains",
+ "suite": "Suite 879",
+ "city": "Wisokyburgh",
+ "zipcode": "90566-7771",
+ "geo": {
+ "lat": "-43.9509",
+ "lng": "-34.4618"
+ }
+ },
+ "phone": "010-692-6593 x09125",
+ "website": "anastasia.net",
+ "company": {
+ "name": "Deckow-Crist",
+ "catchPhrase": "Proactive didactic contingency",
+ "bs": "synergize scalable supply-chains"
+ }
+ },
+ {
+ "id": 3,
+ "name": "Clementine Bauch",
+ "username": "Samantha",
+ "email": "Nathan@yesenia.net",
+ "address": {
+ "street": "Douglas Extension",
+ "suite": "Suite 847",
+ "city": "McKenziehaven",
+ "zipcode": "59590-4157",
+ "geo": {
+ "lat": "-68.6102",
+ "lng": "-47.0653"
+ }
+ },
+ "phone": "1-463-123-4447",
+ "website": "ramiro.info",
+ "company": {
+ "name": "Romaguera-Jacobson",
+ "catchPhrase": "Face to face bifurcated interface",
+ "bs": "e-enable strategic applications"
+ }
+ },
+ {
+ "id": 4,
+ "name": "Patricia Lebsack",
+ "username": "Karianne",
+ "email": "Julianne.OConner@kory.org",
+ "address": {
+ "street": "Hoeger Mall",
+ "suite": "Apt. 692",
+ "city": "South Elvis",
+ "zipcode": "53919-4257",
+ "geo": {
+ "lat": "29.4572",
+ "lng": "-164.2990"
+ }
+ },
+ "phone": "493-170-9623 x156",
+ "website": "kale.biz",
+ "company": {
+ "name": "Robel-Corkery",
+ "catchPhrase": "Multi-tiered zero tolerance productivity",
+ "bs": "transition cutting-edge web services"
+ }
+ },
+ {
+ "id": 5,
+ "name": "Chelsey Dietrich",
+ "username": "Kamren",
+ "email": "Lucio_Hettinger@annie.ca",
+ "address": {
+ "street": "Skiles Walks",
+ "suite": "Suite 351",
+ "city": "Roscoeview",
+ "zipcode": "33263",
+ "geo": {
+ "lat": "-31.8129",
+ "lng": "62.5342"
+ }
+ },
+ "phone": "(254)954-1289",
+ "website": "demarco.info",
+ "company": {
+ "name": "Keebler LLC",
+ "catchPhrase": "User-centric fault-tolerant solution",
+ "bs": "revolutionize end-to-end systems"
+ }
+ },
+ {
+ "id": 6,
+ "name": "Mrs. Dennis Schulist",
+ "username": "Leopoldo_Corkery",
+ "email": "Karley_Dach@jasper.info",
+ "address": {
+ "street": "Norberto Crossing",
+ "suite": "Apt. 950",
+ "city": "South Christy",
+ "zipcode": "23505-1337",
+ "geo": {
+ "lat": "-71.4197",
+ "lng": "71.7478"
+ }
+ },
+ "phone": "1-477-935-8478 x6430",
+ "website": "ola.org",
+ "company": {
+ "name": "Considine-Lockman",
+ "catchPhrase": "Synchronised bottom-line interface",
+ "bs": "e-enable innovative applications"
+ }
+ },
+ {
+ "id": 7,
+ "name": "Kurtis Weissnat",
+ "username": "Elwyn.Skiles",
+ "email": "Telly.Hoeger@billy.biz",
+ "address": {
+ "street": "Rex Trail",
+ "suite": "Suite 280",
+ "city": "Howemouth",
+ "zipcode": "58804-1099",
+ "geo": {
+ "lat": "24.8918",
+ "lng": "21.8984"
+ }
+ },
+ "phone": "210.067.6132",
+ "website": "elvis.io",
+ "company": {
+ "name": "Johns Group",
+ "catchPhrase": "Configurable multimedia task-force",
+ "bs": "generate enterprise e-tailers"
+ }
+ },
+ {
+ "id": 8,
+ "name": "Nicholas Runolfsdottir V",
+ "username": "Maxime_Nienow",
+ "email": "Sherwood@rosamond.me",
+ "address": {
+ "street": "Ellsworth Summit",
+ "suite": "Suite 729",
+ "city": "Aliyaview",
+ "zipcode": "45169",
+ "geo": {
+ "lat": "-14.3990",
+ "lng": "-120.7677"
+ }
+ },
+ "phone": "586.493.6943 x140",
+ "website": "jacynthe.com",
+ "company": {
+ "name": "Abernathy Group",
+ "catchPhrase": "Implemented secondary concept",
+ "bs": "e-enable extensible e-tailers"
+ }
+ },
+ {
+ "id": 9,
+ "name": "Glenna Reichert",
+ "username": "Delphine",
+ "email": "Chaim_McDermott@dana.io",
+ "address": {
+ "street": "Dayna Park",
+ "suite": "Suite 449",
+ "city": "Bartholomebury",
+ "zipcode": "76495-3109",
+ "geo": {
+ "lat": "24.6463",
+ "lng": "-168.8889"
+ }
+ },
+ "phone": "(775)976-6794 x41206",
+ "website": "conrad.com",
+ "company": {
+ "name": "Yost and Sons",
+ "catchPhrase": "Switchable contextually-based project",
+ "bs": "aggregate real-time technologies"
+ }
+ },
+ {
+ "id": 10,
+ "name": "Clementina DuBuque",
+ "username": "Moriah.Stanton",
+ "email": "Rey.Padberg@karina.biz",
+ "address": {
+ "street": "Kattie Turnpike",
+ "suite": "Suite 198",
+ "city": "Lebsackbury",
+ "zipcode": "31428-2261",
+ "geo": {
+ "lat": "-38.2386",
+ "lng": "57.2232"
+ }
+ },
+ "phone": "024-648-3804",
+ "website": "ambrose.net",
+ "company": {
+ "name": "Hoeger LLC",
+ "catchPhrase": "Centralized empowering task-force",
+ "bs": "target end-to-end models"
+ }
+ }
+]
\ No newline at end of file
diff --git a/cypress/integration/VueAutonumeric.spec.js b/cypress/integration/VueAutonumeric.spec.js
new file mode 100644
index 0000000..7b6762b
--- /dev/null
+++ b/cypress/integration/VueAutonumeric.spec.js
@@ -0,0 +1,315 @@
+// import mount from 'cypress-vue-unit-test';
+const mountVue = require('cypress-vue-unit-test');
+// import AutoNumeric from '../../node_modules/autonumeric/dist/autoNumeric'; //FIXME Finish this
+import VueAutonumeric from '../../src/components/VueAutonumeric.vue'; //FIXME Fails
+
+describe('Declarative rendering', () => {
+ // Vue code from https://vuejs.org/v2/guide/#Declarative-Rendering
+ const template = `
{{ message }}
`;
+
+ const data = {
+ message: 'Hello Vue!',
+ };
+
+ // that's all you need to do
+ beforeEach(mountVue({ template, data }));
+
+ it('shows hello', () => {
+ cy.contains('Hello Vue!');
+ });
+
+ it('changes message if data changes', () => {
+ // mounted Vue instance is available under Cypress.vue
+ Cypress.vue.message = 'Vue rocks!';
+ cy.contains('Vue rocks!');
+ });
+});
+
+describe('VueAutonumeric.vue', () => {
+ // beforeEach(mountVue(VueAutonumeric));
+
+ // fit('should generate an input by default', () => {
+ // const wrapper = mountVue(VueAutonumeric);
+ // expect(wrapper.is('input')).toBe(true);
+ // expect(wrapper.attributes().type).toEqual('text');
+ // expect(wrapper.attributes().value).toEqual('');
+ // expect(wrapper.isEmpty()).toBe(true);
+ // });
+
+ /*
+ it('should correctly be formatted', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 1234567.78,
+ },
+ });
+ expect(wrapper.is('input')).toBe(true);
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+ });
+
+ it('should correctly be formatted after its value is modified by a user interaction', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 1234567.78,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+ const input = wrapper.find('input');
+ expect(input.element.value).toEqual('1.234.567,78 €');
+
+ // Test inputting a number
+ input.trigger('click'); //FIXME Is this really needed? Isn't the focus already on the input since it's the generated DOM element?
+ input.trigger('keydown.home');
+ input.trigger('keydown', { //FIXME Fails (see https://github.com/vuejs/vue-test-utils/issues/484)
+ key: '1',
+ keyCode: 49,
+ which: 49,
+ });
+ expect(input.element.value).toEqual('11.234.567,78 €');
+ expect(wrapper.vm.anElement.rawValue).toEqual('11234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('11.234.567,78 €');
+ });
+
+ it('should correctly be formatted after its value is modified without a user interaction, via setting the input `value`', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 1234567.78,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+
+ // Modify the input value programmatically
+ const input = wrapper.find('input');
+ input.element.value = 221100;
+ expect(wrapper.element.value).toEqual('221.100,00 €'); //FIXME Fails : received 221100; this is not formatted and the `rawValue` is not updated
+ expect(wrapper.vm.value).toEqual('221100'); //FIXME Fails
+ expect(wrapper.vm.anElement.rawValue).toEqual('221100'); //FIXME Fails
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('221.100,00 €');
+ });
+
+ it('should correctly be formatted after its value is modified without a user interaction, via props', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 1234567.78,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+
+ wrapper.setProps({ value: '221100' });
+ expect(wrapper.vm.value).toEqual('221100');
+ expect(wrapper.element.value).toEqual('221.100,00 €');
+ expect(wrapper.vm.anElement.rawValue).toEqual('221100');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('221.100,00 €');
+ });
+
+ it('should correctly be formatted after multiple option updates', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 1234567.78,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+
+ wrapper.setProps({ options: 'dollar' });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('$1,234,567.78');
+
+ wrapper.setProps({ options: 'euro' });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+
+ wrapper.setProps({ options: ['euro', { currencySymbol: '#' }] });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78#');
+ });
+
+ it('should correctly set the decimal place precision when updating the options, then the value', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 1234567.7812,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+
+ wrapper.setProps({ options: 'percentageEU3dec' });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567.780,000 %'); //FIXME Fails
+
+ wrapper.setProps({ value: 0.00123456 }); //FIXME Fails
+ expect(wrapper.vm.anElement.rawValue).toEqual('0.001234');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('0,123 %');
+ });
+
+ it('should save the maximal `decimalPlaces` option between options updates in order to keep the correct precision', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 221456.72,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('221456.72');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('221.456,72 €');
+
+ wrapper.setProps({ options: ['dollar', { decimalPlaces: 5 }] });
+ expect(wrapper.vm.anElement.rawValue).toEqual('221456.72');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('$221,456.72000');
+
+ // Then modify the decimal places
+ const input = wrapper.find('input');
+ input.trigger('click'); //FIXME Is this really needed? Isn't the focus already on the input since it's the generated DOM element?
+ input.trigger('keydown.end');
+ input.trigger('keydown.left');
+ input.trigger('keydown.left');
+ input.trigger('keydown.left'); // Position ourselves here: '$221,456.72|000'
+ input.trigger('keydown', { //FIXME Fails (see https://github.com/vuejs/vue-test-utils/issues/484)
+ key: '8',
+ keyCode: 56,
+ which: 56,
+ });
+ input.trigger('keydown', {
+ key: '2',
+ keyCode: 50,
+ which: 50,
+ });
+ input.trigger('keydown', {
+ key: '2',
+ keyCode: 50,
+ which: 50,
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('221456.72882');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('$221,456.72882');
+
+ // Switch back to option that have a lesser number of decimal places
+ wrapper.setProps({ options: ['euro'] });
+ expect(wrapper.vm.anElement.rawValue).toEqual('221456.72882');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('221.456,72 €');
+
+ // ...then finally switch back to the option with 5 decimal places; that data should not have been 'deleted' when switching to the previous options
+ wrapper.setProps({ options: ['dollar', { decimalPlaces: 5 }] });
+ expect(wrapper.vm.anElement.rawValue).toEqual('221456.72882');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('$221,456.72882');
+ });
+
+ it('should correctly update the options and value when using a single object to change those two at the same time', () => {
+ // It should correctly set the decimal place precision during a combined option and value update
+ let obj = {
+ val : 123456.78,
+ options: 'euro',
+ };
+
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: obj.options,
+ value : obj.val,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('123456.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('123.456,78 €');
+
+ // Update the options and value at the same time:
+ obj = {
+ options : 'percentageEU3dec',
+ val : 0.00123456,
+ };
+ expect(wrapper.vm.anElement.rawValue).toEqual('0.001234'); //FIXME Fails
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1,234 %');
+
+ // And back the original options/values
+ obj.val = 123456.78;
+ obj.options = 'euro';
+ expect(wrapper.vm.anElement.rawValue).toEqual('123456.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('123.456,78 €');
+ });
+
+ it('should be generated with the `id` and `name` passed as attributes', () => {
+ const id = 'theIdToUse';
+ const name = 'theInputName';
+ const wrapper = mount(VueAutonumeric, {
+ attrs: {
+ id,
+ name,
+ },
+ });
+ expect(wrapper.is('input')).toBe(true);
+ expect(wrapper.attributes().id).toEqual(id); //FIXME Fails (see https://github.com/vuejs/vue-test-utils/issues/483)
+ expect(wrapper.attributes().name).toEqual(name); //FIXME Fails
+ });
+
+ it('should be generated with the `placeholder` attribute passed as a prop', () => {
+ const placeholderText = 'This is my placeholder';
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ placeholder: placeholderText,
+ },
+ });
+ expect(wrapper.is('input')).toBe(true);
+ expect(wrapper.attributes().placeholder).toEqual(placeholderText);
+ });
+
+ it('should correctly generate a `div` element when using the `tag` prop, and set the `contenteditable` attribute', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ tag: 'div',
+ },
+ });
+ expect(wrapper.is('input')).toBe(false);
+ expect(wrapper.is('div')).toBe(true);
+ expect(wrapper.attributes().contenteditable).toBeTruthy();
+ });
+
+ it('should correctly generate a `p` element when using the `tag` prop, and set the `contenteditable` attribute', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ tag: 'p',
+ },
+ });
+ expect(wrapper.is('input')).toBe(false);
+ expect(wrapper.is('p')).toBe(true);
+ expect(wrapper.attributes().contenteditable).toBeTruthy();
+ });
+
+ it('should bubble up the AutoNumeric events to the parent', () => {
+ const wrapper = mount(VueAutonumeric, {
+ propsData: {
+ options: 'euro',
+ value : 1234567.78,
+ },
+ });
+ expect(wrapper.vm.anElement.rawValue).toEqual('1234567.78');
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('1.234.567,78 €');
+ const input = wrapper.find('input');
+ expect(input.element.value).toEqual('1.234.567,78 €');
+
+ // Test inputting a number
+ input.trigger('click'); //FIXME Is this really needed? Isn't the focus already on the input since it's the generated DOM element?
+ input.trigger('keydown.home');
+ input.trigger('keydown', { //FIXME Fails (see https://github.com/vuejs/vue-test-utils/issues/484)
+ key: '1',
+ keyCode: 49,
+ which: 49,
+ });
+ //FIXME Finish this: How to test that the native AutoNumeric events are correctly bubbling up?
+ expect(wrapper.emittedByOrder()[2].args[0]).toEqual('11234567.78'); //FIXME Fails
+ expect(wrapper.vm.anElement.getFormatted()).toEqual('11.234.567,78 €');
+ });
+
+ xit('should correctly format the input value when a shared v-model is modified by another instance of VueAutonumeric', () => { //FIXME Finish this
+ const wrapper = mount(VueAutonumeric);
+ expect(wrapper.is('input')).toBe(true);
+ });
+ */
+
+ //FIXME Finish this: test the `resetOnOptions` and `tag` props
+});
diff --git a/cypress/integration/example_spec.js b/cypress/integration/example_spec.js
new file mode 100644
index 0000000..4561239
--- /dev/null
+++ b/cypress/integration/example_spec.js
@@ -0,0 +1,1557 @@
+//
+// **** Kitchen Sink Tests ****
+//
+// This app was developed to demonstrate
+// how to write tests in Cypress utilizing
+// all of the available commands
+//
+// Feel free to modify this spec in your
+// own application as a jumping off point
+
+// Please read our "Introduction to Cypress"
+// https://on.cypress.io/introduction-to-cypress
+
+describe('Kitchen Sink', () => {
+ it('.should() - assert that is correct', () => {
+ // https://on.cypress.io/visit
+ cy.visit('https://example.cypress.io');
+
+ // Here we've made our first assertion using a '.should()' command.
+ // An assertion is comprised of a chainer, subject, and optional value.
+
+ // https://on.cypress.io/should
+ // https://on.cypress.io/and
+
+ // https://on.cypress.io/title
+ cy.title().should('include', 'Kitchen Sink');
+ // ↲ ↲ ↲
+ // subject chainer value
+ });
+
+ context('Querying', () => {
+ beforeEach(() => {
+ // Visiting our app before each test removes any state build up from
+ // previous tests. Visiting acts as if we closed a tab and opened a fresh one
+ cy.visit('https://example.cypress.io/commands/querying');
+ });
+
+ // Let's query for some DOM elements and make assertions
+ // The most commonly used query is 'cy.get()', you can
+ // think of this like the '$' in jQuery
+
+ it('cy.get() - query DOM elements', () => {
+ // https://on.cypress.io/get
+
+ // Get DOM elements by id
+ cy.get('#query-btn').should('contain', 'Button');
+
+ // Get DOM elements by class
+ cy.get('.query-btn').should('contain', 'Button');
+
+ cy.get('#querying .well>button:first').should('contain', 'Button');
+ // ↲
+ // Use CSS selectors just like jQuery
+ });
+
+ it('cy.contains() - query DOM elements with matching content', () => {
+ // https://on.cypress.io/contains
+ cy.get('.query-list')
+ .contains('bananas')
+ .should('have.class', 'third');
+
+ // we can pass a regexp to `.contains()`
+ cy.get('.query-list')
+ .contains(/^b\w+/)
+ .should('have.class', 'third');
+
+ cy.get('.query-list')
+ .contains('apples')
+ .should('have.class', 'first');
+
+ // passing a selector to contains will yield the selector containing the text
+ cy.get('#querying')
+ .contains('ul', 'oranges')
+ .should('have.class', 'query-list');
+
+ // `.contains()` will favor input[type='submit'],
+ // button, a, and label over deeper elements inside them
+ // this will not yield the inside the button,
+ // but the