Fix merge conflicts

This commit is contained in:
Santiago Lo Coco 2023-12-04 19:48:59 -03:00
parent 8b05695ce3
commit 76751ba003
26 changed files with 440 additions and 24 deletions

View File

@ -1,6 +1,7 @@
node_modules
Dockerfile.prod
Dockerfile.test
Dockerfile.dev
docker-compose.dev.yml
docker-compose.yml
docker-template.yml

View File

@ -0,0 +1,18 @@
FROM node:17.9.1 AS app
WORKDIR /app
COPY package.json .
COPY package-lock.json .
RUN npm install
COPY . .
ENV REACT_APP_ENDPOINT "http://host.docker.internal:5001"
RUN npm run build
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
RUN rm -rf ./*
COPY --from=app /app/build .
COPY nginx/default-dev.conf /etc/nginx/conf.d/default.conf
EXPOSE 8000
ENTRYPOINT ["nginx", "-g", "daemon off;"]

View File

@ -7,4 +7,6 @@ services:
file: docker-template.yml
service: browser-client
container_name: fids-browser-dev_browser-client
extra_hosts:
- "host.docker.internal:host-gateway"
network_mode: host

View File

@ -0,0 +1,15 @@
server {
listen 8000;
location / {
root /usr/share/nginx/html;
index unresolvable-file-html.html;
try_files $uri @index;
}
location @index {
root /usr/share/nginx/html;
add_header Cache-Control no-cache;
expires 0;
try_files /index.html =404;
}
}

View File

@ -47,6 +47,7 @@ export const CreateFlight = () => {
<input
type="text"
value={flightData.flight_code}
name="Code"
onChange={(e) =>
setFlightData({ ...flightData, flight_code: e.target.value })
}
@ -56,6 +57,7 @@ export const CreateFlight = () => {
Status:
<input
type="text"
name="Status"
value={flightData.status}
onChange={(e) =>
setFlightData({ ...flightData, status: e.target.value })
@ -67,6 +69,7 @@ export const CreateFlight = () => {
<input
type="text"
value={flightData.origin}
name="Origin"
onChange={(e) =>
setFlightData({ ...flightData, origin: e.target.value })
}
@ -76,6 +79,7 @@ export const CreateFlight = () => {
Destination:
<input
type="text"
name="Destination"
value={flightData.destination}
onChange={(e) =>
setFlightData({ ...flightData, destination: e.target.value })
@ -86,6 +90,7 @@ export const CreateFlight = () => {
Departure Time:
<input
type="text"
name="DepartureTime"
value={flightData.departure_time}
onChange={(e) =>
setFlightData({ ...flightData, departure_time: e.target.value })
@ -96,6 +101,7 @@ export const CreateFlight = () => {
Arrival Time:
<input
type="text"
name="ArrivalTime"
value={flightData.arrival_time}
onChange={(e) =>
setFlightData({ ...flightData, arrival_time: e.target.value })
@ -106,11 +112,12 @@ export const CreateFlight = () => {
Gate:
<input
type="text"
name="Gate"
value={flightData.gate}
onChange={(e) => setFlightData({ ...flightData, gate: e.target.value })}
/>
</label>
<button type="submit">Submit</button>
<button name="CreateFlightButton" type="submit">Submit</button>
</form>
);
};

View File

@ -52,7 +52,7 @@ export const Home: React.FC<Props> = (props) => {
return (
<div className="Box">
{isAirline ? <button onClick={() => { navigate("/create-flight") }}>Create flight</button> : <></>}
{isAirline ? <button name="CreateFlight" onClick={() => { navigate("/create-flight") }}>Create flight</button> : <></>}
{isAdmin ? <button onClick={() => { navigate("/create-airline") }}>Create airline user</button> : <></>}
<h2>Flights</h2>
<div className="Items">

View File

@ -16,10 +16,12 @@ export const LogIn = () => {
<div className="Section">
<Input
placeholder="User"
name="User"
onChange={(ev) => setEmail(ev.target.value)}
/>
<Input.Password
placeholder="Password"
name="Password"
onChange={(ev) => setPassword(ev.target.value)}
/>
<Button
@ -27,6 +29,7 @@ export const LogIn = () => {
onClick={async () =>
login({ email, password })
}
name="Login"
loading={loading}
>
Log in
@ -36,6 +39,7 @@ export const LogIn = () => {
onClick={() =>
navigate("/signup")
}
name="Signup"
>
Sign up
</Button>

View File

@ -19,18 +19,22 @@ export const SignUp = () => {
<Input
type="email"
placeholder="Email"
name="Email"
onChange={(ev) => setEmail(ev.target.value)}
/>
<Input
placeholder="Username"
name="User"
onChange={(ev) => setUsername(ev.target.value)}
/>
<Input.Password
placeholder="Password"
name="Password"
onChange={(ev) => setPassword(ev.target.value)}
/>
<Input.Password
placeholder="Repeat password"
name="PasswordRep"
onChange={(ev) => setRepeatPassword(ev.target.value)}
/>
<Button
@ -38,6 +42,7 @@ export const SignUp = () => {
onClick={async () =>
await createUser({ email, password, username })
}
name="Signup"
loading={isLoading}
disabled={
email === "" ||

View File

@ -25,7 +25,12 @@ app.add_middleware(
"https://airport.fids.slc.ar",
"http://localhost:8080",
"http://localhost:8081",
"http://localhost:8000",
"http://localhost:8001",
"http://host.docker.internal:8000",
"http://host.docker.internal:8001",
"http://localhost:3000",
"http://192.168.1.127:3000",
],
allow_credentials=True,
allow_methods=["POST", "GET", "PUT", "DELETE", "OPTIONS", "PATCH"],

View File

@ -1 +1,3 @@
API_URL=http://localhost:5000
API_URL=http://localhost:5000
POSTGRES_USER=username
POSTGRES_PASS=password

1
testing/catcher/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
package*.json

View File

@ -1,7 +1,22 @@
FROM slococo/python-builder:3.11.2
USER root
RUN apt update && apt install libpq-dev -y
RUN apt update && apt install libpq-dev nodejs firefox-esr -y
RUN apt install -y ca-certificates curl gnupg
RUN mkdir -p /etc/apt/keyrings
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_16.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
RUN apt remove nodejs -y
RUN apt update && apt install wget nodejs -y
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.30.0/geckodriver-v0.30.0-linux64.tar.gz \
&& mkdir -p /usr/lib/selenium && tar -xf geckodriver-v0.30.0-linux64.tar.gz -C /usr/bin/ \
&& chmod +x /usr/bin/geckodriver
RUN npm install selenium-webdriver
RUN apt install chromium chromium-driver -y
USER 999
RUN python -m pip install --upgrade pip && \

View File

@ -0,0 +1,18 @@
FROM slococo/python-builder:3.11.2
USER root
RUN apt update && apt install libpq-dev -y
USER 999
RUN python -m pip install --upgrade pip && \
python -m pip install catcher catcher-modules[postgres]
COPY --chown=python:python . .
RUN chmod +x /usr/src/app/test.sh
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ARG API_URL
ENV API_URL $API_URL
ENTRYPOINT ["/usr/src/app/test.sh"]

View File

@ -6,15 +6,18 @@ services:
image: ${API_IMAGE}
environment:
- API_URL=${API_URL}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASS=${POSTGRES_PASS}
# entrypoint: ["/bin/bash","-c"]
# command:
# - "sleep 120"
# - "sleep 3600"
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- auth
- flights
- gateway
- subscriptions
- catcher
networks:
auth:
@ -29,5 +32,3 @@ networks:
gateway:
name: fids-gateway-dev_gateway
external: true
catcher:
driver: bridge

View File

@ -1,4 +1,6 @@
postgres: 'user:password@auth-db:5432/api_dev'
postgres: '{{ POSTGRES_USER }}:{{ POSTGRES_PASS }}@auth-db:5432/api_dev'
postgres_flights: '{{ POSTGRES_USER }}:{{ POSTGRES_PASS }}@flights-db:5432/api_dev'
users: 'http://fids-auth-dev_auth-api:5000/users'
auth: 'http://fids-auth-dev_auth-api:5000/auth'
gateway: 'http://fids-gateway-dev_api-gw:5002'
browser: 'http://host.docker.internal:8000'

View File

@ -0,0 +1,89 @@
const { Builder, By, Key, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const assert = require('assert');
async function validLogin() {
const driver = await new Builder().forBrowser('chrome')
.setChromeOptions(new chrome.Options()
.addArguments('--headless')
.addArguments('--no-sandbox')
.addArguments('--disable-gpu')
)
.build();
try {
await driver.get(process.env.site_url);
await driver.findElement(By.name('User'))
.sendKeys('info@lufthansa.com');
await driver.findElement(By.name('Password'))
.sendKeys('password1234');
await driver.findElement(By.name('Login')).click();
await driver.wait(until.elementLocated(By.xpath("//h2[text()='Flights']", 5000)))
await driver.wait(until.elementLocated(By.name('CreateFlight'), 5000))
await driver.findElement(By.name('CreateFlight')).click();
await driver.wait(until.urlIs(process.env.site_url + "/create-flight"));
await driver.wait(until.elementLocated(By.name('Gate'), 5000))
const Code = await driver.findElement(By.name('Code'));
const Status = await driver.findElement(By.name('Status'))
const Origin = await driver.findElement(By.name('Origin'))
const Destination = await driver.findElement(By.name('Destination'))
const ArrivalTime = await driver.findElement(By.name('ArrivalTime'))
const DepartureTime = await driver.findElement(By.name('DepartureTime'))
const Gate = await driver.findElement(By.name('Gate'))
await Code.click();
await Code.clear();
await Code.sendKeys(process.env.code);
await Status.click();
await Status.clear();
await Status.sendKeys('Scheduled');
await Origin.click()
await Origin.clear();
await Origin.sendKeys('Salta');
await Destination.click();
await Destination.clear();
await Destination.sendKeys('Buenos aires');
await ArrivalTime.click();
await ArrivalTime.clear();
await ArrivalTime.sendKeys('2023-11-04 05:16 AM');
await DepartureTime.click();
await DepartureTime.clear();
await DepartureTime.sendKeys('2023-11-04 03:11 AM');
await Gate.click();
await Gate.clear();
await Gate.sendKeys('A5');
await driver.wait(until.elementLocated(By.name('CreateFlightButton'), 5000))
await driver.findElement(By.name('CreateFlightButton')).click();
await driver.wait(until.elementLocated(By.xpath("//h2[text()='Flights']", 5000)))
let actualUrl = process.env.site_url + "/home?page=1";
let expectedUrl = await driver.getCurrentUrl();
assert.equal(actualUrl, expectedUrl);
driver.quit();
}
catch (err) {
console.error(err);
process.exitCode = 1;
driver.quit();
}
}
validLogin();

View File

@ -0,0 +1,42 @@
const { Builder, By, Key, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const assert = require('assert');
async function validLogin() {
const driver = await new Builder().forBrowser('chrome')
.setChromeOptions(new chrome.Options()
.addArguments('--headless')
.addArguments('--no-sandbox')
.addArguments('--disable-gpu')
)
.build();
try {
await driver.get(process.env.site_url);
await driver.findElement(By.name('User'))
.sendKeys('info@lufthansa.com');
await driver.findElement(By.name('Password'))
.sendKeys('password1234');
await driver.findElement(By.name('Login')).click();
let title = await driver.getTitle();
assert.equal("Airport browser", title);
await driver.wait(until.elementLocated(By.xpath("//h2[text()='Flights']", 5000)))
let actualUrl = process.env.site_url + "/home?page=1";
let expectedUrl = await driver.getCurrentUrl();
assert.equal(actualUrl, expectedUrl);
driver.quit();
}
catch (err) {
console.error(err);
process.exitCode = 1;
driver.quit();
}
}
validLogin();

View File

@ -0,0 +1,49 @@
const { Builder, By, Key, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const assert = require('assert');
async function validLogin() {
const driver = await new Builder().forBrowser('chrome')
.setChromeOptions(new chrome.Options()
.addArguments('--headless')
.addArguments('--no-sandbox')
.addArguments('--disable-gpu')
)
.build();
try {
await driver.get(process.env.site_url);
await driver.findElement(By.name('Signup')).click();
await driver.wait(until.urlIs(process.env.site_url + "/signup"));
await driver.wait(until.elementLocated(By.name('User'), 5000))
await driver.findElement(By.name('Email'))
.sendKeys(process.env.email);
await driver.findElement(By.name('User'))
.sendKeys(process.env.user)
await driver.findElement(By.name('Password'))
.sendKeys(process.env.password)
await driver.findElement(By.name('PasswordRep'))
.sendKeys(process.env.password)
await driver.findElement(By.name('Signup')).click();
await driver.wait(until.elementLocated(By.xpath("//h2[text()='Flights']", 5000)))
let actualUrl = process.env.site_url + "/home?page=1";
let expectedUrl = await driver.getCurrentUrl();
assert.equal(actualUrl, expectedUrl);
driver.quit();
}
catch (err) {
console.error(err);
process.exitCode = 1;
driver.quit();
}
}
validLogin();

View File

@ -1,3 +1,6 @@
#!/bin/bash
catcher -i inventories/local.yaml tests/*.yaml
catcher -i inventories/local.yaml tests/login.test.yaml
catcher -i inventories/local.yaml tests/create-flight.test.yaml
catcher -i inventories/local.yaml tests/signup.test.yaml
catcher -i inventories/local.yaml tests/auth.test.yaml

View File

@ -11,15 +11,3 @@ steps:
response_code: 2xx
name: 'Login with {{ users[0].email }}'
register: {user_id: '{{ OUTPUT.user_id }}'}
- postgres:
request:
conf: '{{ postgres }}'
sql: 'select * from users where id = {{ user_id }}'
register: {email_in_db: '{{ OUTPUT.email }}'}
- check:
equals: {the: '{{ users[0].email }}', is: '{{ email_in_db }}'}
# finally:
# - postgres:
# request:
# conf: '{{ postgres }}'
# sql: 'delete from users where id = {{ user_id }}'

View File

@ -0,0 +1,22 @@
variables:
site_url: '{{ browser }}'
code: 'VWJ367'
steps:
- selenium:
test:
driver: '/usr/lib/chromedriver'
file: resources/create-flight.js
register: {title: '{{ OUTPUT.title }}'}
- echo: {from: '{{ title }}', to: variable.output}
- postgres:
request:
conf: '{{ postgres_flights }}'
sql: "select count(*) from flights where flight_code = '{{ code }}'"
register: {count: '{{ OUTPUT.count }}'}
- check:
equals: {the: 1, is: '{{ count }}'}
finally:
- postgres:
request:
conf: '{{ postgres_flights }}'
sql: "delete from flights where flight_code = '{{ code }}'"

View File

@ -0,0 +1,9 @@
variables:
site_url: '{{ browser }}'
steps:
- selenium:
test:
driver: '/usr/lib/chromedriver'
file: resources/login.js
register: {title: '{{ OUTPUT.title }}'}
- echo: {from: '{{ title }}', to: variable.output}

View File

@ -0,0 +1,24 @@
variables:
site_url: '{{ browser }}'
email: 'jorge@gmail.com'
user: 'jorge'
password: 'password1234'
steps:
- selenium:
test:
driver: '/usr/lib/chromedriver'
file: resources/signup.js
register: {title: '{{ OUTPUT.title }}'}
- echo: {from: '{{ title }}', to: variable.output}
- postgres:
request:
conf: '{{ postgres }}'
sql: "select count(*) from users where email = '{{ email }}'"
register: {count: '{{ OUTPUT.count }}'}
- check:
equals: {the: 1, is: '{{ count }}'}
finally:
- postgres:
request:
conf: '{{ postgres }}'
sql: "delete from users where email = '{{ email }}'"

View File

@ -1,3 +1,4 @@
#!/bin/bash
tavern-ci *.yaml
tavern-ci test_flights.tavern.yaml
# tavern-ci *.yaml

View File

@ -7,3 +7,56 @@ stages:
method: GET
response:
status_code: 200
---
test_name: Create Flight
stages:
- name: Make sure we can log in
request:
url: "{tavern.env_vars.API_URL}/auth/login"
method: POST
json:
email: info@lufthansa.com
password: password1234
headers:
content-type: application/json
response:
status_code: 200
json:
user_id: 1
access_token: !anystr
refresh_token: !anystr
headers:
content-type: application/json
save:
json:
access_token: access_token
- name: Make sure we can create a flight
request:
url: "{tavern.env_vars.API_URL}/flights"
method: POST
json:
flight_code: 'XAS231'
origin: 'Salta'
destination: 'Buenos Aires'
arrival_time: "2024-04-04 05:16 AM"
departure_time: "2024-04-04 03:11 AM"
gate: 'C5'
status: 'Scheduled'
headers:
content-type: application/json
authorization: Bearer {access_token}
response:
status_code: 200
json:
id: !anyint
flight_code: !anystr
origin: !anystr
destination: !anystr
arrival_time: !anystr
departure_time: !anystr
gate: !anystr
status: !anystr
headers:
content-type: application/json

View File

@ -9,7 +9,7 @@ stages:
email: info@lufthansa.com
password: password1234
headers:
content-type: application/json
content-type: application/json
response:
status_code: 200
json:
@ -18,3 +18,43 @@ stages:
refresh_token: !anystr
headers:
content-type: application/json
---
test_name: Register
stages:
- name: Make sure we can register
request:
url: "{tavern.env_vars.API_URL}/users"
method: POST
json:
username: acosta
email: acosta@gmail.com
password: password1234
headers:
content-type: application/json
response:
status_code: 200
json:
id: !anyint
username: !anystr
email: !anystr
headers:
content-type: application/json
- name: Make sure we can log in
request:
url: "{tavern.env_vars.API_URL}/auth/login"
method: POST
json:
email: acosta@gmail.com
password: password1234
headers:
content-type: application/json
response:
status_code: 200
json:
user_id: !anyint
access_token: !anystr
refresh_token: !anystr
headers:
content-type: application/json