Skip to content

Commit

Permalink
Merge branch 'midudev:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
LucianoGimenezz authored Oct 13, 2023
2 parents 385229d + d8c2c06 commit d308dae
Show file tree
Hide file tree
Showing 31 changed files with 1,346 additions and 3,980 deletions.
18 changes: 18 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'pruebas':
- pruebas/**

'prueba-1':
- pruebas/01-reading-list/**

'prueba-2':
- pruebas/02-bazar-universal/**

'web':
- web/**

'chore':
- .github/**
- .gitignore
- LICENSE
- README.md
- package.json
46 changes: 46 additions & 0 deletions .github/workflows/check_folder_structure.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Check Folder Structure

on:
pull_request:
types: opened

jobs:
check-folder-structure:
runs-on: ubuntu-latest
outputs:
comment: ${{ steps.check.outputs.comment }}
steps:
- uses: actions/checkout@v2
- name: Get changed files
id: changed_files
uses: tj-actions/[email protected]
- name: Check if folder structure is correct
id: check
run: |
PR_USERNAME=$(echo "${{ github.event.pull_request.user.login }}")
FILES="${{ steps.changed_files.outputs.all_modified_files }}"
IFS=' ' read -r -a FILES_ARR <<< "$FILES"
for FILE in "${FILES_ARR[@]}"; do
if [[ ${FILE} == pruebas/* ]]; then
TEST_FOLDER=$(echo ${FILE} | cut -d'/' -f2)
if [[ ${FILE} != pruebas/${TEST_FOLDER}/${PR_USERNAME}/* ]]; then
echo "Incorrect folder structure in file: ${FILE}. Requesting changes."
echo "Asegúrese de que los cambios se realicen en 'pruebas/${TEST_FOLDER}/${PR_USERNAME}/'. :file_folder:" > message.txt
echo "::set-output name=comment::$(cat message.txt)"
break
fi
fi
done
- name: Comment PR
if: steps.check.outputs.comment != ''
uses: actions/github-script@v6
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "${{ steps.check.outputs.comment }}"
})
13 changes: 13 additions & 0 deletions .github/workflows/labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: "Pull Request Labeler"
on:
- pull_request_target
- workflow_dispatch

jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Pruebas técnicas de programación para desarrolladores frontend y backend.
## Lista de pruebas técnicas

- [01 - Reading List (FrontEnd - Nivel: Junior)](./pruebas/01-reading-list/README.md)
- [02 - Bazar Universal (FrontEnd - Nivel: Junior)](./pruebas/02-bazar-universal/README.md)

## ¿Cómo participar?

Expand Down
147 changes: 147 additions & 0 deletions live-coding/01-node-callbacks-promises/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Prueba Técnica JavaScript + Node.js

Escribe las soluciones en el archivo `solutions/index.js` manteniendo el nombre de las funciones y sus `export`. Usa `ESModules` en tu proyecto de Node.js

1 - Arregla esta función para que el código posterior funcione como se espera:

```javascript
import net from 'node:net'

export const ping = (ip) => {
const startTime = process.hrtime()

const client = net.connect({ port: 80, host: ip }, () => {
client.end()
return { time: process.hrtime(startTime), ip }
})

client.on('error', (err) => {
throw err
client.end()
})
}

ping('midu.dev', (err, info) => {
if (err) console.error(err)
console.log(info)
})
```

2 - Transforma la siguiente función para que funcione con promesas en lugar de callbacks:

```javascript
export function obtenerDatosPromise(callback) {
setTimeout(() => {
callback(null, { data: 'datos importantes' });
}, 2000);
}
```

3 - Explica qué hace la funcion. Identifica y corrige los errores en el siguiente código. Si ves algo innecesario, elimínalo. Luego mejoralo para que siga funcionando con callback y luego haz lo que consideres para mejorar su legibilidad.

```javascript
export function procesarArchivo() {
fs.readFile('input.txt', 'utf8', (error, contenido) => {
if (error) {
console.error('Error leyendo archivo:', error.message);
return false;
}

setTimeout(() => {
const textoProcesado = contenido.toUpperCase();

fs.writeFile('output.txt', textoProcesado, error => {
if (error) {
console.error('Error guardando archivo:', error.message);
return false;
}

console.log('Archivo procesado y guardado con éxito');
return true
});

}, 1000);
});
}
```

4 - ¿Cómo mejorarías el siguiente código y por qué? Arregla los tests si es necesario:

```javascript
import fs from 'node:fs';

export function leerArchivos() {
const archivo1 = fs.readSync('archivo1.txt', 'utf8');
const archivo2 = fs.readSync('archivo2.txt', 'utf8');
const archivo3 = fs.readSync('archivo3.txt', 'utf8');

return `${archivo1} ${archivo2} ${archivo3}`
}

leerArchivos();
```

5 - Escribe una funcion `delay` que retorne una promesa que se resuelva después de `n` milisegundos. Por ejemplo:

```javascript
export async function delay () {
// ...
}

delay(3000).then(() => console.log('Hola mundo'));
// o..
await delay(3000)
console.log('Hola mundo')
```

6. Vamos a crear nuestra propia utilidad `dotenv` en el archivo `dotenv.js`.

- La utilidad debe devolver un método `config` que lee el archivo `.env` y añade las variables de entorno que haya en el archivo al objeto `process.env`.

- Por ejemplo si tu archivo `.env` contiene:

```sh
PORT=8080
TOKEN="123abc"
```

Entonces podríamos hacer esto:

```javascript
const dotenv = require("./dotenv.js");
dotenv.config()

console.log(process.env.PORT) // "8008"
console.log(process.env.TOKEN) // "123abc"
```

También se le puede pasar el path del archivo `.env` como parámetro:

```javascript
const dotenv = require("./dotenv.js");
dotenv.config("./config/.env.local")
```

Cosas a tener en cuenta:

- Sólo se permite usar el módulo `fs` para leer el archivo.
- Si el archivo no existe, no debe dar error, simplemente no hace nada.
- Si el archivo existe, pero no tiene ninguna variable de entorno, no debe hacer nada.
- Sólo debe soportar el archivo `.env` o el que se le pasa como parametro, no hace falta que soporte `.env.local`, `.env.development` y similares de forma automática.
- Las variables de entorno siempre son strings, por lo que si en el archivo `.env` hay un número, por ejemplo `PORT=8080`, al leerlo con `fs` y añadirlo a `process.env` debe ser un string, no un número.
- `process.env` es un objeto y, por lo tanto, es mutable. Esto significa que podemos añadir propiedades nuevas sin problemas.


7 - Diseña una API REST utilizando Express que permite a los usuarios crear, leer, modificar, actualizar y eliminar elementos de una lista.

La lista tendrá objetos que tienen la siguiente forma:

```javascript
{
id: 1,
content: 'Item 1'
}
```

Haz la solución en el archivo `solutions/server.js` y exporta el `app` y `server` creado.
Instala Express con `npm install express`. No te preocupes por CORS.
29 changes: 29 additions & 0 deletions live-coding/01-node-callbacks-promises/already-solved/dotenv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { readFileSync } from 'node:fs'

function parseEnv(env) {
const lines = env.split('\n')

lines.forEach(line => {
const [key, ...value] = line.split('=')
const valueString = value.join('')
const hasQuotes = valueString.startsWith('"') && valueString.endsWith('"')
const valueToStore = hasQuotes ? valueString.slice(1, -1) : valueString
process.env[key] = valueToStore
})

}

export function config({ path = '.env' } = {}) {
try {
const env = readFileSync(path, 'utf8')
parseEnv(env)
} catch (e) {
console.error(e)
}
}

const dotenv = {
config
}

export default dotenv
96 changes: 96 additions & 0 deletions live-coding/01-node-callbacks-promises/already-solved/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import net from 'node:net'
import fs from 'node:fs'

export const ping = (ip, callback) => {
const startTime = process.hrtime()

const client = net.connect({ port: 80, host: ip }, () => {
client.end()
callback(null, { time: process.hrtime(startTime), ip })
})

client.on('error', (err) => {
client.end()
callback(err)
})
}

// ping('midu.dev', (err, info) => {
// if (err) console.error(err)
// console.log(info)
// })

export function obtenerDatosPromise() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ data: 'datos importantes' });
}, 2000);
})
}

export function procesarArchivo(callback) {
const handleReadFile = (error, contenido) => {
if (error) {
console.error('Error leyendo archivo:', error.message);
callback(error)
}

const textoProcesado = contenido.toUpperCase();

fs.writeFile('output.txt', textoProcesado, handleWriteFile);
}

const handleWriteFile = error => {
if (error) {
console.error('Error guardando archivo:', error.message);
callback(error)
}

console.log('Archivo procesado y guardado con éxito');
callback(null)
}

fs.readFile('input.txt', 'utf8', handleReadFile);
}

export async function procesarArchivoPromise() {
try {
const file = await fs.promises.readFile('input.txt', 'utf8')
const textoProcesado = file.toUpperCase()
await fs.promises.writeFile('output.txt', textoProcesado)
} catch (error) {
console.error('Error procesando archivo:', error.message)
throw error
}
}

// export function leerArchivos() {
// const archivo1 = fs.readSync('archivo1.txt', 'utf8');
// const archivo2 = fs.readSync('archivo2.txt', 'utf8');
// const archivo3 = fs.readSync('archivo3.txt', 'utf8');

// return `${archivo1} ${archivo2} ${archivo3}`
// }

// leerArchivos();

export async function leerArchivos() {
console.time('leerArchivos')
const [a, b, c] = await Promise.all([
fs.promises.readFile('archivo1.txt', 'utf8'),
fs.promises.readFile('archivo2.txt', 'utf8'),
fs.promises.readFile('archivo3.txt', 'utf8')
])
console.timeEnd('leerArchivos')

return `${a} ${b} ${c}`
}


export async function delay (ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, ms)
})
}
Loading

0 comments on commit d308dae

Please sign in to comment.