Update of the whole app
This commit is contained in:
parent
a5ed530081
commit
b57bdb6b7b
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>HungerGames</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
|
||||
</head>
|
||||
<body>
|
||||
|
2622
package-lock.json
generated
2622
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
51
package.json
51
package.json
@ -16,75 +16,60 @@
|
||||
"dependencies": {
|
||||
"es6-promise": "^4.1.1",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"vue": "^2.5.2",
|
||||
"material-design-icons": "^3.0.1",
|
||||
"vue": "^2.5.8",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuetify": "^0.16.9",
|
||||
"vuex": "^3.0.0"
|
||||
"vuetify": "^0.17.2",
|
||||
"vuex": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.6",
|
||||
"babel-core": "^6.22.1",
|
||||
"babel-eslint": "^8.0.1",
|
||||
"babel-eslint": "^8.0.2",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-istanbul": "^4.1.1",
|
||||
"babel-plugin-transform-runtime": "^6.22.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"babel-register": "^6.22.0",
|
||||
"chai": "^4.1.2",
|
||||
"chalk": "^2.2.0",
|
||||
"chromedriver": "^2.33.2",
|
||||
"connect-history-api-fallback": "^1.4.0",
|
||||
"copy-webpack-plugin": "^4.2.0",
|
||||
"cross-env": "^5.1.0",
|
||||
"connect-history-api-fallback": "^1.5.0",
|
||||
"copy-webpack-plugin": "^4.2.1",
|
||||
"cross-env": "^5.1.1",
|
||||
"cross-spawn": "^5.0.1",
|
||||
"css-loader": "^0.28.0",
|
||||
"cssnano": "^3.10.0",
|
||||
"eslint": "^4.9.0",
|
||||
"eslint": "^4.11.0",
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
"eslint-friendly-formatter": "^3.0.0",
|
||||
"eslint-import-resolver-webpack": "^0.8.1",
|
||||
"eslint-loader": "^1.7.1",
|
||||
"eslint-plugin-html": "^3.0.0",
|
||||
"eslint-plugin-html": "^4.0.0",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"express": "^4.16.2",
|
||||
"extract-text-webpack-plugin": "^3.0.1",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.5",
|
||||
"friendly-errors-webpack-plugin": "^1.1.3",
|
||||
"html-webpack-plugin": "^2.28.0",
|
||||
"http-proxy-middleware": "^0.17.3",
|
||||
"inject-loader": "^3.0.0",
|
||||
"karma": "^1.4.1",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-phantomjs-launcher": "^1.0.2",
|
||||
"karma-phantomjs-shim": "^1.4.0",
|
||||
"karma-sinon-chai": "^1.3.1",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.31",
|
||||
"karma-webpack": "^2.0.5",
|
||||
"mocha": "^4.0.1",
|
||||
"nightwatch": "^0.9.12",
|
||||
"opn": "^5.1.0",
|
||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||
"ora": "^1.2.0",
|
||||
"phantomjs-prebuilt": "^2.1.14",
|
||||
"phantomjs-prebuilt": "^2.1.16",
|
||||
"rimraf": "^2.6.0",
|
||||
"selenium-server": "^3.6.0",
|
||||
"selenium-server": "^3.7.1",
|
||||
"semver": "^5.3.0",
|
||||
"shelljs": "^0.7.6",
|
||||
"sinon": "^4.0.1",
|
||||
"sinon-chai": "^2.14.0",
|
||||
"shelljs": "^0.7.8",
|
||||
"url-loader": "^0.6.2",
|
||||
"vue-loader": "^13.3.0",
|
||||
"vue-loader": "^13.5.0",
|
||||
"vue-style-loader": "^3.0.1",
|
||||
"vue-template-compiler": "^2.5.2",
|
||||
"vue-template-compiler": "^2.5.8",
|
||||
"webpack": "^3.8.1",
|
||||
"webpack-bundle-analyzer": "^2.2.1",
|
||||
"webpack-bundle-analyzer": "^2.9.1",
|
||||
"webpack-dev-middleware": "^1.10.0",
|
||||
"webpack-hot-middleware": "^2.20.0",
|
||||
"webpack-merge": "^4.1.0"
|
||||
"webpack-merge": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0",
|
||||
|
22
src/App.vue
22
src/App.vue
@ -1,19 +1,13 @@
|
||||
<template>
|
||||
<v-app toolbar>
|
||||
<v-app>
|
||||
<NavigationDrawer v-model="isDrawerVisible"/>
|
||||
<v-toolbar color="indigo" dark fixed app clipped-left>
|
||||
<v-toolbar-side-icon @click.stop="showHideDrawer"></v-toolbar-side-icon>
|
||||
<v-toolbar-title>HungerGames</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon>
|
||||
<v-icon>skip_next</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<main>
|
||||
<v-content>
|
||||
<router-view></router-view>
|
||||
</v-content>
|
||||
</main>
|
||||
<v-content class="max-width">
|
||||
<router-view></router-view>
|
||||
</v-content>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
@ -36,3 +30,11 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.max-width {
|
||||
max-width: 1000px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,15 +1,33 @@
|
||||
require('es6-promise').polyfill();
|
||||
require('isomorphic-fetch');
|
||||
|
||||
export const BASEURL = 'https://world.openfoodfacts.org/';
|
||||
export const BASE_URL = 'https://world.openfoodfacts.org';
|
||||
export const BASE_FETCH_PARAMS = {
|
||||
/*
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
Authorization: `Basic ${btoa('off:off')}`,
|
||||
},
|
||||
*/
|
||||
};
|
||||
export const USER_ID = '';
|
||||
export const PASSWORD = '';
|
||||
|
||||
function _fetchFromOFFApi(filters) {
|
||||
let url = BASEURL;
|
||||
let url = BASE_URL;
|
||||
filters.forEach((filter) => {
|
||||
url += `/${filter}`;
|
||||
});
|
||||
|
||||
return fetch(`${url}.json`);
|
||||
return fetch(`${url}.json`, BASE_FETCH_PARAMS);
|
||||
}
|
||||
|
||||
function _sendToOFFApi(barcode, fields) {
|
||||
let url = `${BASE_URL}/cgi/product_jqmp2.pl?code=${barcode}&user_id=${USER_ID}&password=${PASSWORD}`;
|
||||
Object.keys(fields).forEach((field) => {
|
||||
url += `&${field}=${fields[field]}`;
|
||||
});
|
||||
return fetch(url, BASE_FETCH_PARAMS);
|
||||
}
|
||||
|
||||
function missingCategories() {
|
||||
@ -60,8 +78,9 @@ function missingCategories() {
|
||||
|
||||
|
||||
function updateCategories(productId, categories) {
|
||||
// TODO
|
||||
console.log(productId, categories);
|
||||
return _sendToOFFApi(productId, {
|
||||
categories: categories.join(','),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
24
src/components/About.vue
Normal file
24
src/components/About.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<v-container fluid>
|
||||
<v-layout row>
|
||||
<v-flex xs12 class="text-xs-center">
|
||||
<h2>About</h2>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-layout row>
|
||||
<v-flex xs12>
|
||||
<p>
|
||||
This app is a quest-based app to help you update and
|
||||
complete <a href="http://openfoodfacts.org/">OpenFoodFacts</a> data.
|
||||
</p>
|
||||
<p>This app is a free software, released under MIT license.</p>
|
||||
<p>OpenFoodFacts database is a free database licensed under <a href="https://world.openfoodfacts.org/legal">Open Database License</a>.</p>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
};
|
||||
</script>
|
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<v-navigation-drawer
|
||||
persistent
|
||||
fixed
|
||||
clipped
|
||||
app
|
||||
enable-resize-watcher
|
||||
disable-resize-watcher
|
||||
v-model="isActive"
|
||||
>
|
||||
<v-list>
|
||||
|
@ -1,89 +0,0 @@
|
||||
<template>
|
||||
<v-container fluid grid-list-lg class="text-xs-center">
|
||||
<v-layout row mb-3 align-center>
|
||||
<v-flex xs5>
|
||||
<v-dialog v-model="dialog" lazy absolute>
|
||||
<v-avatar
|
||||
size="100%"
|
||||
class="pointable"
|
||||
slot="activator"
|
||||
>
|
||||
<!-- TODO: Should be closable by ESC -->
|
||||
<img class="icon" :src="data.icon" />
|
||||
</v-avatar>
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<!-- TODO: Preload images -->
|
||||
<img style="width: 100%;" :src="data.icon" />
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-flex>
|
||||
<v-flex xs7 class="text-xs-center">
|
||||
<div>
|
||||
<div class="headline">{{ data.brands || 'Unknown' }}</div>
|
||||
<h2 class="title">{{ data.name || 'Unkown' }}</h2>
|
||||
</div>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-divider />
|
||||
<v-layout row>
|
||||
<v-flex xs12>
|
||||
<h2 class="title">Select all correct categories:</h2>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-layout row wrap>
|
||||
<v-btn
|
||||
v-for="(category, key) in data.predictedCategories" :key="key"
|
||||
round dark :class="{ green: category.isOK, red: !category.isOK }"
|
||||
@click.stop="data.predictedCategories[key].isOK = !data.predictedCategories[key].isOK"
|
||||
>
|
||||
{{ category.name }}
|
||||
</v-btn>
|
||||
</v-layout>
|
||||
<v-layout row>
|
||||
<v-flex xs12>
|
||||
<v-btn @click="handleSubmit()">Submit</v-btn>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: Object,
|
||||
onSubmit: Function,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialog: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSubmit() {
|
||||
const okCategories = [];
|
||||
Object.keys(this.data.predictedCategories).forEach((key) => {
|
||||
if (this.data.predictedCategories[key].isOk) {
|
||||
okCategories.push(key);
|
||||
}
|
||||
});
|
||||
this.onSubmit(okCategories);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pointable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pointable:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.icon {
|
||||
border-radius: 0;
|
||||
}
|
||||
</style>
|
66
src/components/Quests/QuestMissingCategories/index.vue
Normal file
66
src/components/Quests/QuestMissingCategories/index.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<v-container fluid grid-list-lg class="text-xs-center">
|
||||
<v-layout row mb-3 align-center>
|
||||
<v-flex xs5>
|
||||
<ZoomableImage :url="questData.icon" />
|
||||
</v-flex>
|
||||
<v-flex xs7 class="text-xs-center">
|
||||
<div>
|
||||
<div class="headline">{{ questData.brands || 'Unknown' }}</div>
|
||||
<h2 class="title">{{ questData.name || 'Unkown' }}</h2>
|
||||
</div>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-divider />
|
||||
<v-layout row>
|
||||
<v-flex xs12>
|
||||
<h2 class="title">Select all correct categories:</h2>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-layout row wrap>
|
||||
<v-btn
|
||||
v-for="(category, key) in questData.predictedCategories" :key="key"
|
||||
round dark :class="{ green: category.isOk, red: !category.isOk }"
|
||||
@click.stop="handleClick(key)"
|
||||
>
|
||||
{{ category.name }}
|
||||
</v-btn>
|
||||
</v-layout>
|
||||
<v-layout row>
|
||||
<v-flex xs12>
|
||||
<v-btn @click="handleSubmit()">Submit</v-btn>
|
||||
or <a @click="onSkip()">Skip</a>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ZoomableImage from '@/components/ZoomableImage';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ZoomableImage,
|
||||
},
|
||||
props: {
|
||||
questData: Object,
|
||||
onSubmit: Function,
|
||||
onSkip: Function,
|
||||
},
|
||||
methods: {
|
||||
handleSubmit() {
|
||||
const okCategories = [];
|
||||
Object.keys(this.questData.predictedCategories).forEach((key) => {
|
||||
if (this.questData.predictedCategories[key].isOk) {
|
||||
okCategories.push(this.questData.predictedCategories[key].name);
|
||||
}
|
||||
});
|
||||
this.onSubmit(okCategories);
|
||||
},
|
||||
handleClick(key) {
|
||||
this.questData.predictedCategories[key].isOk =
|
||||
!this.questData.predictedCategories[key].isOk;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
57
src/components/Quests/index.vue
Normal file
57
src/components/Quests/index.vue
Normal file
@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-layout row v-if="isLoading">
|
||||
<v-flex xs12>
|
||||
<p>Loading quests…</p>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<template v-else>
|
||||
<QuestMissingCategories v-if="questData" :questData="questData" :onSubmit="validateQuest" :onSkip="skipQuest" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import QuestMissingCategories from '@/components/Quests/QuestMissingCategories/index';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
error: null,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
QuestMissingCategories,
|
||||
},
|
||||
created() {
|
||||
this.fetchData();
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.isLoading = true;
|
||||
this.$store.dispatch('preloadQuests').then(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
validateQuest(solution) {
|
||||
this.$store.dispatch('validateQuest', {
|
||||
type: this.questData.type,
|
||||
id: this.questData.id,
|
||||
solution,
|
||||
});
|
||||
},
|
||||
skipQuest() {
|
||||
this.$store.dispatch('skipQuest', {
|
||||
type: this.questData.type,
|
||||
id: this.questData.id,
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
questData() {
|
||||
return this.$store.getters.popQuest;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
72
src/components/ZoomableImage.vue
Normal file
72
src/components/ZoomableImage.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<v-dialog v-model="dialog">
|
||||
<v-avatar
|
||||
size="100%"
|
||||
class="pointable"
|
||||
slot="activator"
|
||||
>
|
||||
<!-- TODO: Should be closable by ESC -->
|
||||
<img class="icon" :src="url" />
|
||||
</v-avatar>
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<!-- TODO: Preload images -->
|
||||
<img class="zoomed-image" :src="url" />
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
url: String,
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('keydown', this.handleEscKey);
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.removeEventListener('keydown', this.handleEscKey);
|
||||
},
|
||||
methods: {
|
||||
handleEscKey(e) {
|
||||
if (
|
||||
this.dialog && (
|
||||
e.key === 'Escape' ||
|
||||
e.key === 'Esc' ||
|
||||
e.keyCode === 27
|
||||
)
|
||||
) {
|
||||
this.dialog = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialog: false,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pointable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pointable:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.icon {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.zoomed-image {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
@ -3,6 +3,7 @@
|
||||
import Vue from 'vue';
|
||||
import Vuetify from 'vuetify';
|
||||
import 'vuetify/dist/vuetify.min.css';
|
||||
import 'material-design-icons/iconfont/material-icons.css';
|
||||
|
||||
import App from './App';
|
||||
import router from './router';
|
||||
|
@ -1,7 +1,8 @@
|
||||
import Vue from 'vue';
|
||||
import Router from 'vue-router';
|
||||
import About from '@/views/About';
|
||||
import Quest from '@/views/Quest';
|
||||
|
||||
import About from '@/components/About';
|
||||
import Quests from '@/components/Quests';
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
@ -10,7 +11,7 @@ export default new Router({
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: Quest,
|
||||
component: Quests,
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
|
@ -4,25 +4,28 @@ import quests from './quests';
|
||||
|
||||
export default {
|
||||
preloadQuests({ commit }) {
|
||||
commit(types.IS_LOADING_QUESTS);
|
||||
|
||||
const apiRequests = [];
|
||||
Object.keys(quests).forEach((quest) => {
|
||||
quests[quest]().then(
|
||||
items => commit(
|
||||
types.STORE_QUESTS_ITEMS,
|
||||
{
|
||||
type: 'missingCategories',
|
||||
items,
|
||||
},
|
||||
apiRequests.push(
|
||||
quests[quest]().then(
|
||||
items => commit(
|
||||
types.STORE_QUESTS_ITEMS,
|
||||
{
|
||||
type: 'missingCategories',
|
||||
items,
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
return Promise.all(apiRequests);
|
||||
},
|
||||
|
||||
validateQuest({ commit }, { type, id, solution }) {
|
||||
if (type === 'missingCategories') {
|
||||
updateCategories(id, solution).then(() => commit(
|
||||
types.VALIDATE_QUEST,
|
||||
types.REMOVE_QUEST_ITEM,
|
||||
{
|
||||
type,
|
||||
id,
|
||||
@ -30,4 +33,14 @@ export default {
|
||||
));
|
||||
}
|
||||
},
|
||||
|
||||
skipQuest({ commit }, { type, id }) {
|
||||
commit(
|
||||
types.REMOVE_QUEST_ITEM,
|
||||
{
|
||||
type,
|
||||
id,
|
||||
},
|
||||
);
|
||||
},
|
||||
};
|
||||
|
@ -1,3 +1,2 @@
|
||||
export const IS_LOADING_QUESTS = 'IS_LOADING_QUESTS';
|
||||
export const STORE_QUESTS_ITEMS = 'STORE_QUESTS_ITEMS';
|
||||
export const VALIDATE_QUEST = 'VALIDATE_QUEST';
|
||||
export const REMOVE_QUEST_ITEM = 'REMOVE_QUEST_ITEM';
|
||||
|
@ -3,20 +3,19 @@ import Vue from 'vue';
|
||||
import * as types from './mutations-types';
|
||||
|
||||
export const initialState = {
|
||||
isLoading: false,
|
||||
questsItems: {},
|
||||
};
|
||||
|
||||
export const mutations = {
|
||||
[types.IS_LOADING_QUESTS](state) {
|
||||
state.isLoading = true;
|
||||
},
|
||||
[types.STORE_QUESTS_ITEMS](state, { type, items }) {
|
||||
Vue.set(state.questsItems, type, items);
|
||||
},
|
||||
[types.VALIDATE_QUEST](state, { id, type }) {
|
||||
[types.REMOVE_QUEST_ITEM](state, { type, id }) {
|
||||
const items = state.questsItems[type];
|
||||
delete items[id];
|
||||
const index = items.findIndex(item => item.id === id);
|
||||
if (index > -1) {
|
||||
items.splice(index, 1);
|
||||
}
|
||||
Vue.set(state.questsItems, type, items);
|
||||
},
|
||||
};
|
||||
|
@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<v-container fluid>
|
||||
<v-layout row>
|
||||
<v-flex xs12>
|
||||
<h2>About</h2>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-layout row>
|
||||
<v-flex xs12>
|
||||
<p>TODO</p>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
};
|
||||
</script>
|
@ -1,35 +0,0 @@
|
||||
<template>
|
||||
<QuestMissingCategories v-if="questData" :data="questData" :onSubmit="validateQuest" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import QuestMissingCategories from '@/components/QuestMissingCategories/index';
|
||||
|
||||
|
||||
// TODO: Changing route should not flash old product
|
||||
export default {
|
||||
components: {
|
||||
QuestMissingCategories,
|
||||
},
|
||||
created() {
|
||||
this.fetchData();
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.$store.dispatch('preloadQuests');
|
||||
},
|
||||
validateQuest(solution) {
|
||||
this.$store.dispatch('validateQuest', {
|
||||
type: this.questData.type,
|
||||
id: this.questData.id,
|
||||
solution,
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
questData() {
|
||||
return this.$store.getters.popQuest;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -1,24 +0,0 @@
|
||||
// A custom Nightwatch assertion.
|
||||
// the name of the method is the filename.
|
||||
// can be used in tests like this:
|
||||
//
|
||||
// browser.assert.elementCount(selector, count)
|
||||
//
|
||||
// for how to write custom assertions see
|
||||
// http://nightwatchjs.org/guide#writing-custom-assertions
|
||||
exports.assertion = function (selector, count) {
|
||||
this.message = `Testing if element <${selector}> has count: ${count}`;
|
||||
this.expected = count;
|
||||
this.pass = function (val) {
|
||||
return val === this.expected;
|
||||
};
|
||||
this.value = function (res) {
|
||||
return res.value;
|
||||
};
|
||||
this.command = function (cb) {
|
||||
const self = this;
|
||||
return this.api.execute(selector => document.querySelectorAll(selector).length, [selector], (res) => {
|
||||
cb.call(self, res);
|
||||
});
|
||||
};
|
||||
};
|
@ -1,46 +0,0 @@
|
||||
require('babel-register');
|
||||
const config = require('../../config');
|
||||
|
||||
// http://nightwatchjs.org/gettingstarted#settings-file
|
||||
module.exports = {
|
||||
src_folders: ['test/e2e/specs'],
|
||||
output_folder: 'test/e2e/reports',
|
||||
custom_assertions_path: ['test/e2e/custom-assertions'],
|
||||
|
||||
selenium: {
|
||||
start_process: true,
|
||||
server_path: require('selenium-server').path,
|
||||
host: '127.0.0.1',
|
||||
port: 4444,
|
||||
cli_args: {
|
||||
'webdriver.chrome.driver': require('chromedriver').path,
|
||||
},
|
||||
},
|
||||
|
||||
test_settings: {
|
||||
default: {
|
||||
selenium_port: 4444,
|
||||
selenium_host: 'localhost',
|
||||
silent: true,
|
||||
globals: {
|
||||
devServerURL: `http://localhost:${process.env.PORT || config.dev.port}`,
|
||||
},
|
||||
},
|
||||
|
||||
chrome: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true,
|
||||
},
|
||||
},
|
||||
|
||||
firefox: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'firefox',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
// 1. start the dev server using production config
|
||||
process.env.NODE_ENV = 'testing';
|
||||
const server = require('../../build/dev-server.js');
|
||||
|
||||
server.ready.then(() => {
|
||||
// 2. run the nightwatch test suite against it
|
||||
// to run in additional browsers:
|
||||
// 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
|
||||
// 2. add it to the --env flag below
|
||||
// or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
|
||||
// For more information on Nightwatch's config file, see
|
||||
// http://nightwatchjs.org/guide#settings-file
|
||||
let opts = process.argv.slice(2);
|
||||
if (opts.indexOf('--config') === -1) {
|
||||
opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']);
|
||||
}
|
||||
if (opts.indexOf('--env') === -1) {
|
||||
opts = opts.concat(['--env', 'chrome']);
|
||||
}
|
||||
|
||||
const spawn = require('cross-spawn');
|
||||
const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' });
|
||||
|
||||
runner.on('exit', (code) => {
|
||||
server.close();
|
||||
process.exit(code);
|
||||
});
|
||||
|
||||
runner.on('error', (err) => {
|
||||
server.close();
|
||||
throw err;
|
||||
});
|
||||
});
|
@ -1,19 +0,0 @@
|
||||
// For authoring Nightwatch tests, see
|
||||
// http://nightwatchjs.org/guide#usage
|
||||
|
||||
module.exports = {
|
||||
'default e2e tests': function test(browser) {
|
||||
// automatically uses dev Server port from /config.index.js
|
||||
// default: http://localhost:8080
|
||||
// see nightwatch.conf.js
|
||||
const devServer = browser.globals.devServerURL;
|
||||
|
||||
browser
|
||||
.url(devServer)
|
||||
.waitForElementVisible('#app', 5000)
|
||||
.assert.elementPresent('.hello')
|
||||
.assert.containsText('h1', 'Welcome to Your Vue.js App')
|
||||
.assert.elementCount('img', 1)
|
||||
.end();
|
||||
},
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"globals": {
|
||||
"expect": true,
|
||||
"sinon": true
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
// require all test files (files that ends with .spec.js)
|
||||
const testsContext = require.context('./specs', true, /\.spec$/);
|
||||
testsContext.keys().forEach(testsContext);
|
||||
|
||||
// require all src files except main.js for coverage.
|
||||
// you can also change this to match only the subset of files that
|
||||
// you want coverage for.
|
||||
const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/);
|
||||
srcContext.keys().forEach(srcContext);
|
@ -1,33 +0,0 @@
|
||||
// This is a karma config file. For more details see
|
||||
// http://karma-runner.github.io/0.13/config/configuration-file.html
|
||||
// we are also using it with karma-webpack
|
||||
// https://github.com/webpack/karma-webpack
|
||||
|
||||
const webpackConfig = require('../../build/webpack.test.conf');
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// to run in additional browsers:
|
||||
// 1. install corresponding karma launcher
|
||||
// http://karma-runner.github.io/0.13/config/browsers.html
|
||||
// 2. add it to the `browsers` array below.
|
||||
browsers: ['PhantomJS'],
|
||||
frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
|
||||
reporters: ['spec', 'coverage'],
|
||||
files: ['./index.js'],
|
||||
preprocessors: {
|
||||
'./index.js': ['webpack', 'sourcemap'],
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
noInfo: true,
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: './coverage',
|
||||
reporters: [
|
||||
{ type: 'lcov', subdir: '.' },
|
||||
{ type: 'text-summary' },
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import Hello from '@/components/Hello';
|
||||
|
||||
describe('Hello.vue', () => {
|
||||
it('should render correct contents', () => {
|
||||
const Constructor = Vue.extend(Hello);
|
||||
const vm = new Constructor().$mount();
|
||||
expect(vm.$el.querySelector('.hello h1').textContent)
|
||||
.to.equal('Welcome to Your Vue.js App');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user