From e1dd642dbaa9f1cc52054c3cdc5f4cd767ef8143 Mon Sep 17 00:00:00 2001 From: ivy Date: Thu, 24 Aug 2023 09:24:25 -0500 Subject: [PATCH 1/6] cambios de css web apis y html --- tests-read-only/oa/oa-css.spec.js | 146 +++++++++++++++++--------- tests-read-only/oa/oa-html.spec.js | 12 ++- tests-read-only/oa/oa-web-api.spec.js | 64 +++++------ 3 files changed, 133 insertions(+), 89 deletions(-) diff --git a/tests-read-only/oa/oa-css.spec.js b/tests-read-only/oa/oa-css.spec.js index 473bdfe..587d1c5 100644 --- a/tests-read-only/oa/oa-css.spec.js +++ b/tests-read-only/oa/oa-css.spec.js @@ -1,12 +1,9 @@ -/* global describe, it, expect */ -/* eslint no-undef: "error" */ -/* eslint-env node */ /** * @jest-environment jsdom */ import fs from 'fs'; import css from 'css'; -import { renderItems } from '../../src/viewFunctions.js'; +import { renderView } from '../../src/viewFunctions.js'; const html = fs.readFileSync('./src/index.html', 'utf-8'); document.body.innerHTML = html; @@ -14,7 +11,8 @@ const stylesPath = document.querySelector('link[rel="stylesheet"]').getAttribute const style = fs.readFileSync('./src/' + stylesPath, 'utf-8'); const { rules } = css.parse(style).stylesheet; -const BOX_MODEL_ATTRIBUTES = ['width', 'height', 'margin', 'padding', 'border', 'box-sizing', 'background']; +const BOX_MODEL_ATTRIBUTES = ['width', 'height', 'margin', 'padding', 'border', 'box-sizing']; +const FLEXBOX_DECLARATION = ['display', 'flex']; const FLEXBOX_ATTRIBUTES = ['flex-wrap', 'flex-direction', 'justify-content', 'align-items']; const getRulesForSelector = (selector) => { @@ -25,15 +23,27 @@ const getRulesForSelector = (selector) => { ); } -const tagRulesCSS = (tag) =>{ - const tagClasses = Array.from(tag.classList.values()); - return tagClasses.reduce((allRules, tagClass) => { - const rules = getRulesForSelector(`.${tagClass}`); - const tagRulesAttributes = rules[0].declarations.map((declaration) => declaration.property); - return allRules.concat(tagRulesAttributes); +// returns an array of css declaration objects in format +// [{ 'display": 'block' }, { 'justify-content': 'center' }]; +const getCSSDeclarationsForRules = (rules) => { + return rules.reduce((total, rule) => { + const declarations = rule.declarations.map(({ property, value }) => ({ [property]: value })); + return [...total, ...declarations]; }, []); +} +// get css for an el's classes +// returns in format [{ 'display': 'block' }, { 'justify-content': 'center'}]; +const getDeclarationsForElClasses = (el) => { + const elClasses = Array.from(el.classList.values()); + return elClasses.reduce((allDeclarations, className) => { + const rules = getRulesForSelector(`.${className}`); + // there can be more than one rule for a class + const declarationsForClass = getCSSDeclarationsForRules(rules); + return [...allDeclarations, ...declarationsForClass]; + }, []); } + const fakeData = [ { name: "charizard", @@ -53,44 +63,20 @@ const fakeData = [ ], }, ]; -document.querySelector('#root').innerHTML = renderItems(fakeData); +document.querySelector('#root').innerHTML = renderView(fakeData); describe('CSS', () => { - const cardsLi = document.querySelectorAll('#root > ul > li'); + const elementsLi = document.querySelectorAll('#root > ul > li'); describe('Uso de selectores de CSS', () => { - it('li elementos tienen class', () => { - cardsLi.forEach((li)=>{ - const liClasses = Array.from(li.classList.values()); - if(liClasses.length){ - const liRulesAttributes = tagRulesCSS(li); - expect(liRulesAttributes.length).toBeGreaterThan(0); - } - expect(liClasses.length).toBeGreaterThan(0); + it('elementos
  • tienen un class con CSS', () => { + // all lis should have same classes since rendered dinamically + // so not checking for common classes here + elementsLi.forEach((li) => { + const liRulesAttributes = getDeclarationsForElClasses(li); + expect(liRulesAttributes.length).toBeGreaterThan(0); }); }); - it('El contenedor padre de las etiquetas select usa flexbox', () => { - const parentContainer = document.querySelector('.flexNav'); - const selects = parentContainer.querySelectorAll('select') - if(selects.length > 0){ - const rules = getRulesForSelector(`.flexNav`); - const ulRulesAttributes = rules[0].declarations.map((declaration) => declaration.value); - expect(ulRulesAttributes).toContain('flex'); - } - expect(selects.length).toBeGreaterThan(0); - }); - - it('Uso de flexbox en la clase del ul', () => { - const ul = document.querySelector('#root ul'); - expect( - tagRulesCSS(ul).some( - (attribute) => FLEXBOX_ATTRIBUTES.some( - flexboxAttribute => attribute.startsWith(flexboxAttribute) - ) - ) - ).toBe(true); - }); - it('Se usan selectores CSS de tipo para
    ', () => { const headerRules = getRulesForSelector('header'); expect(headerRules.length).toBeGreaterThan(0); @@ -107,19 +93,75 @@ describe('CSS', () => { }); }); - describe('Modelo de caja (box model)', () => { + describe('Uso de flexbox', () => { + it('Uso de flexbox en el elemento de
      ', () => { + const ul = document.querySelector('#root ul'); + const cssForTag = getCSSDeclarationsForRules(getRulesForSelector(ul.tagName.toLowerCase())); + const cssForId = getCSSDeclarationsForRules(getRulesForSelector(`#${ul.id}`)); + const cssForClasses = getDeclarationsForElClasses(ul); + const cssDeclarations = [...cssForClasses, cssForId, cssForTag]; + + // expect to have display: flex + expect( + cssDeclarations.some((declaration) => { + const [ flexboxProperty, flexboxValue ] = FLEXBOX_DECLARATION; + const [ property, value ] = Object.entries(declaration)[0]; + return property === flexboxProperty && value === flexboxValue; + }) + ).toBe(true); + // and at least one other flexbox property + expect( + cssDeclarations.some((declaration) => { + const [ property ] = Object.entries(declaration)[0]; + return FLEXBOX_ATTRIBUTES.includes(property); + }) + ).toBe(true); + }); + + it('Los elementos ', () => { const select = document.querySelectorAll('select'); + it('La aplicación usa un tiene atributo "name"', () => { Array.from(select).forEach((element) => { - expect(element.getAttribute('name')).not.toBeNull(); + expect(element.getAttribute('name').length).toBeGreaterThan(0); }) + expect(select.length).toBeGreaterThan(0); }); it(' - - + + - +
      diff --git a/src/main.js b/src/main.js index 003a296..033016b 100644 --- a/src/main.js +++ b/src/main.js @@ -7,9 +7,9 @@ const dataGOT = data.got console.log(dataGOT); const root = document.getElementById('root') -const selectFilter = document.querySelector('#select-filter') -const selectSort = document.querySelector('#select-sort') -const buttonFact = document.getElementById('button-fact') +const selectFilter = document.querySelector('#filter') +const selectSort = document.querySelector('#sort') +const buttonFact = document.querySelector('#button-fact') const buttonReset = document.getElementById('button-reset') // eslint-disable-next-line no-undef diff --git a/src/style.css b/src/style.css index e1b81dd..e18ca15 100644 --- a/src/style.css +++ b/src/style.css @@ -17,6 +17,6 @@ form { list-style: none; } -li { +li, .test { border: 1px solid black; -} \ No newline at end of file +} diff --git a/src/viewFunctions.js b/src/viewFunctions.js index f89ba9f..56260d7 100644 --- a/src/viewFunctions.js +++ b/src/viewFunctions.js @@ -3,17 +3,17 @@ export const renderItems = (data) => { let template = ''; data.forEach(element => { template += ` -
    • -
      +
    • +
      -
      Name:
      ${element.fullName}
      +
      Name:
      ${element.firstName}
      ${element.fullName}
      House:
      ${element.family}
      Title:
      ${element.title}
    • ` }); - cardContainer.innerHTML = template + cardContainer.innerHTML = template; return cardContainer }; diff --git a/tests-read-only/e2e/app.spec.js b/tests-read-only/e2e/app.spec.js index d980aed..d184596 100644 --- a/tests-read-only/e2e/app.spec.js +++ b/tests-read-only/e2e/app.spec.js @@ -9,22 +9,24 @@ test.describe('Pagina interraciones', () => { const getItempropValues = async (page, property) => { const liElements = await page.$$(liSelector); const values = await Promise.all(liElements.map(async li => { + // const html = await li.innerHTML(); + // console.log(html); const value = await li.$eval(`[itemprop=${property}]`, (el) => el.textContent); return value; })); return values; }; - const getDataIds = (elements) => Promise.all(elements.map(async (el) => await el.getAttribute('data-id'))); + const getDataIds = (elements) => Promise.all(elements.map(async (el) => await el.getAttribute('data-id'))); const getSortOptions = async (page) => { - const selectSortEl = await page.$('#select-sort'); - let sortByProperty = await selectSortEl.getAttribute('name'); + const selectSortEl = await page.getByTestId('select-sort') + let sortByProperty = await selectSortEl.getAttribute('name'); const sortOrderEl = await page.$('[name="sort-order"]'); if (!sortOrderEl) { // simple sort UI with just one type of sort const sortOrder = await selectSortEl.getAttribute('value'); - return { + return { selectSortEl, sortByProperty, sortOrderEl: selectSortEl, @@ -34,9 +36,9 @@ test.describe('Pagina interraciones', () => { const sortOrder = await sortOrderEl.getAttribute('value'); sortByProperty = await selectSortEl.getAttribute('name'); - return { + return { selectSortEl, - sortByProperty, + sortByProperty, sortOrderEl, sortOrder } @@ -58,7 +60,7 @@ test.describe('Pagina interraciones', () => { test.describe('sort', () => { let sortOrderEl, sortByProperty; - + test.beforeEach(async ({ page }) => { await page.goto('http://localhost:3000/'); ({ sortOrderEl, sortByProperty } = await getSortOptions(page)); @@ -66,7 +68,7 @@ test.describe('Pagina interraciones', () => { test('de ascendente "asc" a descendente "desc"', async ({ page }) => { // await sortOrderEl.selectOption(sortOptions.asc); - await selectSortOrder(sortOrderEl,sortOptions.asc); + await selectSortOrder(sortOrderEl,sortOptions.asc); const sortedValuesAsc = await getItempropValues(page, sortByProperty); await selectSortOrder(sortOrderEl,sortOptions.desc); @@ -90,12 +92,11 @@ test.describe('Pagina interraciones', () => { test.describe('filter', () => { - let selectFilter, filterProperty; + let selectFilter; test.beforeEach(async ({ page }) => { await page.goto('http://localhost:3000/'); - selectFilter = await page.$('#select-filter'); - filterProperty = await selectFilter.getAttribute('name'); + selectFilter = await page.getByTestId('select-filter'); }); test(`cuando elige un filter a otro los resultados se cambian`, async ({ page }) => { @@ -117,7 +118,7 @@ test.describe('Pagina interraciones', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:3000/'); - selectFilter = await page.$('#select-filter'); + selectFilter = await page.getByTestId('select-filter'); ({ sortOrderEl, sortByProperty } = await getSortOptions(page)); }); @@ -126,11 +127,11 @@ test.describe('Pagina interraciones', () => { // sacamos los valores de propiedad en el orden que ocurre en la pagina // sin sort - const valuesNoSorted = await getItempropValues(page, sortByProperty); + const valuesNoSorted = await getItempropValues(page, sortByProperty); await selectSortOrder(sortOrderEl,sortOptions.asc); const valuesSortedAsc = await getItempropValues(page, sortByProperty); - + // await sortOrderEl.selectOption(sortOptions.desc); await selectSortOrder(sortOrderEl,sortOptions.desc); const valuesSortedDesc = await getItempropValues(page, sortByProperty); @@ -139,15 +140,15 @@ test.describe('Pagina interraciones', () => { expect(valuesSortedDesc).toEqual([...valuesNoSorted].sort().reverse()); }); - test('el button "button-reset" limpia los filtros y sort, volvemos a los resultados original', async ({ page }) => { + test('el button "button-clear" limpia los filtros y sort, volvemos a los resultados original', async ({ page }) => { await page.goto('http://localhost:3000/'); const originalLis = await page.$$(liSelector); - const select = await page.$('#select-filter'); + const select = await page.getByTestId('select-filter'); await select.selectOption({ index: 1 }); const liElements = await page.$$(liSelector); expect(liElements.length).not.toEqual(originalLis.length); // probar si no hay mismo cantidad elementos - const buttonReset = await page.$('#button-reset'); + const buttonReset = await page.getByTestId('button-clear'); await buttonReset.click(); const clearLiElements = await page.$$(liSelector); expect(clearLiElements.length).toEqual(originalLis.length); diff --git a/tests-read-only/oa/oa-css.spec.js b/tests-read-only/oa/oa-css.spec.js index 4393cf2..373f53a 100644 --- a/tests-read-only/oa/oa-css.spec.js +++ b/tests-read-only/oa/oa-css.spec.js @@ -5,6 +5,8 @@ import fs from 'fs'; import css from 'css'; import { renderItems } from '../../src/viewFunctions.js'; +import { data as fakeData } from '../../test/data.js'; + const html = fs.readFileSync('./src/index.html', 'utf-8'); document.body.innerHTML = html; @@ -16,6 +18,18 @@ const BOX_MODEL_ATTRIBUTES = ['width', 'height', 'margin', 'padding', 'border', const FLEXBOX_DECLARATION = ['display', 'flex']; const FLEXBOX_ATTRIBUTES = ['flex-wrap', 'flex-direction', 'justify-content', 'align-items']; +const renderDOM = (data) => { + const items = renderItems(data); + // function renderItems can return html string or an node element + if (typeof items === 'string') { + document.querySelector('#root').innerHTML = items; + } else if (items instanceof HTMLElement) { + document.querySelector('#root').appendChild(items); + } else { + throw new Error('Error: renderItems should return an HTML string or an HTMLElement'); + } +} + const getRulesForSelector = (selector) => { return rules.filter( (rule) => @@ -45,51 +59,23 @@ const getDeclarationsForElClasses = (el) => { }, []); } -const fakeData = [ - { - name: "charizard", - img: "https://www.serebii.net/pokemongo/pokemon/006.png", - num: '006', - type: [ - "fire", - "flying" - ], - }, - { - name: "charmeleon", - img: "https://www.serebii.net/pokemongo/pokemon/005.png", - num: '005', - type: [ - "fire" - ], - }, -]; -// document.querySelector('#root').innerHTML = renderItems(fakeData); -// console.log(document.querySelector('#root').innerHTML, "inner ++++++++++++"); - describe('CSS', () => { describe('Uso de selectores de CSS', () => { beforeEach(() => { - const items = renderItems(fakeData); - // function renderItems can return html string or an node element - if (typeof items === 'string') { - document.querySelector('#root').innerHTML = items; - } else if (items instanceof HTMLElement) { - document.querySelector('#root').appendChild(items); - } + renderDOM(fakeData); }); it('elementos
    • tienen un class con CSS', () => { const elementsLi = document.querySelectorAll('#root > ul > li'); - expect(elementsLi.length).toBeGreaterThan(0); // all lis should have same classes since rendered dinamically // so not checking for common classes here elementsLi.forEach((li) => { const liRulesAttributes = getDeclarationsForElClasses(li); expect(liRulesAttributes.length).toBeGreaterThan(0); }); + expect.hasAssertions(); }); it('Se usan selectores CSS de tipo para
      ', () => { @@ -111,12 +97,7 @@ describe('CSS', () => { describe('Uso de flexbox', () => { beforeEach(() => { - const items = renderItems(fakeData); - if (typeof items === 'string') { - document.querySelector('#root').innerHTML = items; - } else if (items instanceof HTMLElement) { - document.querySelector('#root').appendChild(items); - } + renderDOM(fakeData); }); it('Uso de flexbox en el elemento de
        ', () => { diff --git a/tests-read-only/oa/oa-html.spec.js b/tests-read-only/oa/oa-html.spec.js index ceb3e8b..c5653c4 100644 --- a/tests-read-only/oa/oa-html.spec.js +++ b/tests-read-only/oa/oa-html.spec.js @@ -3,34 +3,35 @@ */ import fs from 'fs'; import { renderItems } from '../../src/viewFunctions.js'; +import { data as fakeData } from '../../test/data.js'; + const html = fs.readFileSync('./src/index.html', 'utf-8'); document.body.innerHTML = html; -const fakeData = [ - { - name: "charizard", - img: "https://www.serebii.net/pokemongo/pokemon/006.png", - num: '006', - type: [ - "fire", - "flying" - ], - }, - { - name: "charmeleon", - img: "https://www.serebii.net/pokemongo/pokemon/005.png", - num: '005', - type: [ - "fire" - ], - }, -]; -document.querySelector('#root').innerHTML = renderItems(fakeData); + +const renderDOM = (data) => { + const items = renderItems(data); + // function renderItems can return html string or an node element + if (typeof items === 'string') { + document.querySelector('#root').innerHTML = items; + } else if (items instanceof HTMLElement) { + document.querySelector('#root').appendChild(items); + } else { + throw new Error('Error: renderItems should return an HTML string or an HTMLElement'); + } +} describe('Uso de HTML semántico', () => { + + beforeEach(() => { + renderDOM(fakeData); + }); describe('
        ', () => { - const header = document.querySelector('header'); - const h1 = header.querySelector('h1'); + let header, h1; + beforeEach(() => { + header = document.querySelector('header'); + h1 = header.querySelector('h1'); + }); it('La aplicación usa un
        ', () => { expect(header).not.toBeNull(); @@ -58,7 +59,10 @@ describe('Uso de HTML semántico', () => { }); describe('', () => { expect(select.length).toBeGreaterThan(0); @@ -68,14 +72,14 @@ describe('Uso de HTML semántico', () => { Array.from(select).forEach((element) => { expect(element.getAttribute('name').length).toBeGreaterThan(0); }) - expect(select.length).toBeGreaterThan(0); + expect.hasAssertions(); }); it('