Skip to content
Snippets Groups Projects
Commit 5fe644f4 authored by robinwilliam.hundt's avatar robinwilliam.hundt
Browse files

Better ui for file download

parent 421a5078
Branches
Tags
No related merge requests found
Pipeline #99644 failed
from django.db import transaction
from rest_framework.response import Response
from rest_framework.views import APIView
......@@ -13,8 +15,10 @@ from core.serializers.tutor import TutorSerializer
words = xp.generate_wordlist(wordfile=xp.locate_wordfile(), min_length=5, max_length=8)
@transaction.atomic
def _set_student_passwords():
student_password_dict = {}
# TODO use bulk update with django makepassword function
for student in UserAccount.get_students():
password = xp.generate_xkcdpassword(words, numwords=3, delimiter='-')
student.set_password(password)
......
......@@ -12,13 +12,15 @@
"test:unit": "vue-cli-service test:unit --require mock-local-storage"
},
"dependencies": {
"@types/downloadjs": "^1.4.1",
"axios": "^0.18.0",
"downloadjs": "^1.4.7",
"highlight.js": "^9.12.0",
"v-clipboard": "^2.0.1",
"vue": "^2.5.16",
"vue-class-component": "^6.0.0",
"vue-property-decorator": "^7.3.0",
"vue-notification": "^1.3.12",
"vue-property-decorator": "^7.3.0",
"vue-router": "^3.0.1",
"vuetify": "^1.1.9",
"vuex": "^3.0.1",
......
......@@ -8,12 +8,14 @@
<div v-if="!mapFileLoaded">
If you select a mapping file, the anonymized data
will be mapped back automatically and locally on your machine.
<v-layout row align-center>
<file-select v-model="mapFile" display-text="Select map file" class="ma-3"/>
<span>Without the mapping, the data will still be obfuscated.</span>
</v-layout>
</div>
<span>
<b>NOTE:</b> Mapping / setting passwords can take some time depending on course size.
</span>
<v-layout row>
<v-flex xs4>
<v-tooltip top>
......@@ -42,7 +44,8 @@
@click="exportDialog = false"
>close</v-btn>
<v-spacer/>
<v-btn id="export-data-download-btn" flat outline @click="getExportFile('data')"
<v-progress-circular v-if="loading" indeterminate/>
<v-btn v-else id="export-data-download-btn" flat outline @click="getExportFile('data')"
>{{mapFile || mapFileLoaded ? 'Download and apply mapping' : 'Download without mapping'}}</v-btn>
</v-card-actions>
</v-card-text>
......@@ -66,6 +69,7 @@ export default class DataExport extends mixins(exportMixin) {
mapFile: File | null = null
setPasswords = false
exportType = ExportType.CSV
loading = false
get studentMap () { return getters.state.studentMap }
......@@ -84,18 +88,6 @@ export default class DataExport extends mixins(exportMixin) {
}
})
}
createDownloadPopup (content: string | StudentExportItem[], fileType: ExportType): void {
const blobProperties: BlobPropertyBag = {}
if (fileType === ExportType.JSON) {
blobProperties.type = 'application/json'
content = JSON.stringify(content)
} else {
blobProperties.type = 'text/csv'
}
const blobData = new Blob([<string> content], blobProperties)
window.open(window.URL.createObjectURL(blobData))
}
}
</script>
......
<template>
<div>
<v-menu>
<v-menu offset-y>
<v-tooltip bottom slot="activator">
<v-btn id="export-btn" :color="exportColor" slot="activator">
export
......
......@@ -8,19 +8,22 @@
<div v-if="!mapFileLoaded">
If you select a mapping file, the anonymized data
will be mapped back automatically and locally on your machine.
<v-layout row align-center>
<file-select v-model="mapFile" display-text="Select map file" class="ma-3"/>
<span>Without the mapping, the data will still be obfuscated.</span>
</v-layout>
</div>
<span>
<b>NOTE:</b> Mapping can take some time depending on course size.
</span>
<v-card-actions>
<v-btn
flat color="blue lighten-2"
@click="exportDialog = false"
>close</v-btn>
<v-spacer/>
<v-btn id="instance-export-dl" flat outline @click="getExportFile('instance')"
<v-progress-circular v-if="loading" indeterminate/>
<v-btn v-else id="instance-export-dl" flat outline @click="getExportFile('instance')"
>{{mapFile || mapFileLoaded ? 'Download and apply mapping' : 'Download without mapping'}}</v-btn>
</v-card-actions>
</v-card-text>
......@@ -43,6 +46,7 @@ export default class DataExport extends mixins(exportMixin) {
exportDialog = true
mapFile: File | null = null
exportType = ExportType.JSON // instance export is only available as JSON
loading = false
get studentMap () { return getters.state.studentMap }
......@@ -62,14 +66,6 @@ export default class DataExport extends mixins(exportMixin) {
}
})
}
createDownloadPopup (content: string | InstanceExportData): void {
const blobProperties: BlobPropertyBag = {}
blobProperties.type = 'application/json'
content = JSON.stringify(content)
const blobData = new Blob([<string> content], blobProperties)
window.open(window.URL.createObjectURL(blobData))
}
}
</script>
......
......@@ -4,10 +4,17 @@ import { fetchStudentExportData, StudentExportItem, InstanceExportData, fetchIns
import { getters } from '@/store/getters'
import { mutations as mut } from '@/store/mutations'
import parseCSVMapMixin from '@/components/mixins/parseCSVMapMixin'
import originalDownload from 'downloadjs'
let download = originalDownload;
export enum ExportType {
JSON = 'JSON',
CSV = 'CSV'
JSON = 'application/json',
CSV = 'text/csv'
}
export function mock(mockedDownload?: () => boolean) {
download = mockedDownload || originalDownload
}
@Component
......@@ -16,6 +23,7 @@ export class exportMixin extends mixins(Vue, parseCSVMapMixin) {
mapFile: File | null = null
setPasswords = false
exportType = ExportType.CSV
loading = false
get mapFileLoaded () {
return Object.keys(getters.state.studentMap).length > 0
......@@ -26,6 +34,8 @@ export class exportMixin extends mixins(Vue, parseCSVMapMixin) {
}
async getExportFile (type: string) {
this.loading = true
let studentData
if (type === 'data') {
studentData = await fetchStudentExportData({ setPasswords: this.setPasswords })
......@@ -76,10 +86,11 @@ export class exportMixin extends mixins(Vue, parseCSVMapMixin) {
optionalConvertAndCreatePopup (studentData: StudentExportItem[] | InstanceExportData) {
const convertedData = this.exportType === ExportType.CSV
? this.jsonToCSV(studentData as StudentExportItem[]) : studentData
? this.jsonToCSV(studentData as StudentExportItem[]) : JSON.stringify(studentData)
// we have a cast here because only student export may be converted to csv
this.createDownloadPopup(convertedData, this.exportType)
const filename = this.exportType === ExportType.CSV ? 'export.csv' : 'export.json'
download(convertedData, filename, this.exportType)
this.loading = false
}
async getMappedExportFile (studentData: StudentExportItem[] | InstanceExportData) {
......@@ -126,5 +137,4 @@ export class exportMixin extends mixins(Vue, parseCSVMapMixin) {
}
applyMapping (exportData: StudentExportItem[] | InstanceExportData): void { throw new Error('Not implemented.') }
createDownloadPopup (content: string | StudentExportItem[] | InstanceExportData, fileType: ExportType): void { throw new Error('Not implemented.') }
}
......@@ -8,6 +8,7 @@ import VueRouter from 'vue-router'
import testUtils from '@/../tests/utils/testUtils'
import * as api from '@/api'
import { mock } from '@/components/mixins/exportMixin';
chai.should()
let localVue = createLocalVue()
......@@ -51,11 +52,11 @@ describe('DataExport Component Unit Tests', () => {
let spy = sinon.spy()
// @ts-ignore
sinon.replace(wrapper.vm, 'jsonToCSV', spy)
// @ts-ignore
sinon.replace(wrapper.vm, 'createDownloadPopup', sinon.spy())
mock(spy)
// @ts-ignore
wrapper.vm.optionalConvertAndCreatePopup(testUtils.studentExports)
spy.called.should.equal(true)
mock()
})
it('should download JSON when selected', () => {
let wrapper = mount(DataExport, { localVue: localVue, store })
......@@ -63,11 +64,11 @@ describe('DataExport Component Unit Tests', () => {
let spy = sinon.spy()
// @ts-ignore
sinon.replace(wrapper.vm, 'jsonToCSV', spy)
// @ts-ignore
sinon.replace(wrapper.vm, 'createDownloadPopup', sinon.spy())
mock(() => { return true })
// @ts-ignore
wrapper.vm.optionalConvertAndCreatePopup(testUtils.studentExports)
spy.called.should.equal(false)
mock()
})
it('should download obfuscated data when no mapping was selected', async () => {
let wrapper = mount(DataExport, { localVue: localVue, store })
......
import { ExportType, exportMixin } from '@/components/mixins/exportMixin'
import { ExportType, exportMixin, mock } from '@/components/mixins/exportMixin'
import sinon from 'sinon'
import ax from '@/api'
import testUtils, { FakeFileReader } from '@/../tests/utils/testUtils'
......@@ -59,10 +59,11 @@ describe('Export Mixin Unit Tests', () => {
let spy = sinon.spy()
e.exportType = ExportType.CSV
sinon.replace(e, 'jsonToCSV', stub)
sinon.replace(e, 'createDownloadPopup', spy)
mock(spy)
e.optionalConvertAndCreatePopup(testUtils.studentExports)
stub.calledWith(testUtils.studentExports).should.equal(true)
spy.calledWith('students as csv', ExportType.CSV).should.equal(true)
spy.calledWith('students as csv', 'export.csv', ExportType.CSV).should.equal(true)
mock()
})
})
describe('readMapFileAndCommit', () => {
......
......@@ -140,6 +140,11 @@
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.7.tgz#1b8e33b61a8c09cbe1f85133071baa0dbf9fa71a"
integrity sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==
"@types/downloadjs@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@types/downloadjs/-/downloadjs-1.4.1.tgz#11a959c5fd09d3f1ca74c02ba17ae8f126ce57fd"
integrity sha512-Y7Ds+ne3AMvNY9TB055NCOoFewlmEpRpGGyNaPu1lw6a0reLHWESZ8KLVDBfdOvlwDUBWWQVcijkCJaoysDC4Q==
"@types/highlight.js@^9.12.3":
version "9.12.3"
resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca"
......@@ -2335,6 +2340,11 @@ dot-prop@^4.1.1:
dependencies:
is-obj "^1.0.0"
downloadjs@^1.4.7:
version "1.4.7"
resolved "https://registry.yarnpkg.com/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c"
integrity sha1-9p+W+UDg0FU9rCkROYZaPNAQHjw=
duplexer@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
......
export.json
export.csv
import json
import os
from django.test import LiveServerTestCase
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from core.models import UserAccount
from functional_tests.util import login, create_browser, reset_browser_after_test
from util import factory_boys as fact
def expect_file_to_be_present(path):
def condition(*args):
try:
with open(path):
pass
except FileNotFoundError:
return False
return True
return condition
JSON_EXPORT_FILE = os.path.join(os.path.dirname(__file__), 'export.json')
class ExportTestModal(LiveServerTestCase):
browser: webdriver.Firefox = None
username = None
......@@ -61,7 +77,7 @@ class ExportTestModal(LiveServerTestCase):
exports_btn = self.browser.find_element_by_id('export-btn')
self.assertIn('green', exports_btn.get_attribute('class'))
def test_export_allgood_tooltip_all_corrected(self):
def test_export_all_good_tooltip_all_corrected(self):
self._login()
tooltip_corrected = self.browser.find_element_by_id('corrected-tooltip')
self.assertNotEqual(None, tooltip_corrected)
......@@ -90,16 +106,15 @@ class ExportTestModal(LiveServerTestCase):
data_export_modal = self.browser.find_element_by_id('data-export-modal')
export_type_select = data_export_modal.find_element_by_id('type-select')
export_type_select.click()
export_type_json = data_export_modal.find_element_by_xpath("//*[contains(text(), 'JSON')]")
export_type_json = data_export_modal.find_element_by_xpath("//*[contains(text(), 'json')]")
export_type_json.click()
data_export_btn = data_export_modal.find_element_by_id('export-data-download-btn')
before_click_handles = self.browser.window_handles
data_export_btn.click()
WebDriverWait(self.browser, 10).until(ec.new_window_is_opened(before_click_handles))
tabs = self.browser.window_handles
self.assertEqual(2, len(tabs))
self.browser.switch_to.window(tabs[1])
self.assertIn('B.Inf.4242 Test Module', self.browser.find_element_by_tag_name('body').text)
WebDriverWait(self.browser, 10).until(expect_file_to_be_present(JSON_EXPORT_FILE))
with open(JSON_EXPORT_FILE) as f:
data = json.load(f)
self.assertEqual('B.Inf.4242 Test Module', data[0]['Exam'])
os.remove(JSON_EXPORT_FILE)
def test_export_instance(self):
self._login()
......@@ -110,10 +125,9 @@ class ExportTestModal(LiveServerTestCase):
export_instance.click()
instance_export_modal = self.browser.find_element_by_id('instance-export-modal')
instance_export_btn = instance_export_modal.find_element_by_id('instance-export-dl')
before_click_handles = self.browser.window_handles
instance_export_btn.click()
WebDriverWait(self.browser, 10).until(ec.new_window_is_opened(before_click_handles))
after_click_handles = self.browser.window_handles
self.assertEqual(2, len(after_click_handles))
self.browser.switch_to.window(after_click_handles[1])
self.assertIn('B.Inf.4242 Test Module', self.browser.find_element_by_tag_name('body').text)
WebDriverWait(self.browser, 10).until(expect_file_to_be_present(JSON_EXPORT_FILE))
with open(JSON_EXPORT_FILE) as f:
data = json.load(f)
self.assertEqual('B.Inf.4242 Test Module', data['examTypes'][0]['moduleReference'])
os.remove(JSON_EXPORT_FILE)
......@@ -3,6 +3,7 @@ from itertools import islice
from typing import Sequence
from selenium import webdriver
from selenium.webdriver import FirefoxProfile
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.remote.webelement import WebElement
......@@ -14,7 +15,13 @@ from selenium.common.exceptions import StaleElementReferenceException
def create_browser() -> webdriver.Firefox:
options = Options()
options.headless = bool(os.environ.get('HEADLESS_TESTS', False))
browser = webdriver.Firefox(options=options)
profile = FirefoxProfile()
profile.set_preference("browser.download.folderList", 2)
profile.set_preference("browser.download.dir", os.path.dirname(__file__))
profile.set_preference("browser.download.useDownloadDir", True)
profile.set_preference("browser.download.panel.shown", False)
profile.set_preference("browser.helperApps.neverAsk.saveToDisk", 'application/vnd.hzn-3d-crossword;video/3gpp;video/3gpp2;application/vnd.mseq;application/vnd.3m.post-it-notes;application/vnd.3gpp.pic-bw-large;application/vnd.3gpp.pic-bw-small;application/vnd.3gpp.pic-bw-var;application/vnd.3gp2.tcap;application/x-7z-compressed;application/x-abiword;application/x-ace-compressed;application/vnd.americandynamics.acc;application/vnd.acucobol;application/vnd.acucorp;audio/adpcm;application/x-authorware-bin;application/x-athorware-map;application/x-authorware-seg;application/vnd.adobe.air-application-installer-package+zip;application/x-shockwave-flash;application/vnd.adobe.fxp;application/pdf;application/vnd.cups-ppd;application/x-director;applicaion/vnd.adobe.xdp+xml;application/vnd.adobe.xfdf;audio/x-aac;application/vnd.ahead.space;application/vnd.airzip.filesecure.azf;application/vnd.airzip.filesecure.azs;application/vnd.amazon.ebook;application/vnd.amiga.ami;applicatin/andrew-inset;application/vnd.android.package-archive;application/vnd.anser-web-certificate-issue-initiation;application/vnd.anser-web-funds-transfer-initiation;application/vnd.antix.game-component;application/vnd.apple.installe+xml;application/applixware;application/vnd.hhe.lesson-player;application/vnd.aristanetworks.swi;text/x-asm;application/atomcat+xml;application/atomsvc+xml;application/atom+xml;application/pkix-attr-cert;audio/x-aiff;video/x-msvieo;application/vnd.audiograph;image/vnd.dxf;model/vnd.dwf;text/plain-bas;application/x-bcpio;application/octet-stream;image/bmp;application/x-bittorrent;application/vnd.rim.cod;application/vnd.blueice.multipass;application/vnd.bm;application/x-sh;image/prs.btif;application/vnd.businessobjects;application/x-bzip;application/x-bzip2;application/x-csh;text/x-c;application/vnd.chemdraw+xml;text/css;chemical/x-cdx;chemical/x-cml;chemical/x-csml;application/vn.contact.cmsg;application/vnd.claymore;application/vnd.clonk.c4group;image/vnd.dvb.subtitle;application/cdmi-capability;application/cdmi-container;application/cdmi-domain;application/cdmi-object;application/cdmi-queue;applicationvnd.cluetrust.cartomobile-config;application/vnd.cluetrust.cartomobile-config-pkg;image/x-cmu-raster;model/vnd.collada+xml;text/csv;application/mac-compactpro;application/vnd.wap.wmlc;image/cgm;x-conference/x-cooltalk;image/x-cmx;application/vnd.xara;application/vnd.cosmocaller;application/x-cpio;application/vnd.crick.clicker;application/vnd.crick.clicker.keyboard;application/vnd.crick.clicker.palette;application/vnd.crick.clicker.template;application/vn.crick.clicker.wordbank;application/vnd.criticaltools.wbs+xml;application/vnd.rig.cryptonote;chemical/x-cif;chemical/x-cmdf;application/cu-seeme;application/prs.cww;text/vnd.curl;text/vnd.curl.dcurl;text/vnd.curl.mcurl;text/vnd.crl.scurl;application/vnd.curl.car;application/vnd.curl.pcurl;application/vnd.yellowriver-custom-menu;application/dssc+der;application/dssc+xml;application/x-debian-package;audio/vnd.dece.audio;image/vnd.dece.graphic;video/vnd.dec.hd;video/vnd.dece.mobile;video/vnd.uvvu.mp4;video/vnd.dece.pd;video/vnd.dece.sd;video/vnd.dece.video;application/x-dvi;application/vnd.fdsn.seed;application/x-dtbook+xml;application/x-dtbresource+xml;application/vnd.dvb.ait;applcation/vnd.dvb.service;audio/vnd.digital-winds;image/vnd.djvu;application/xml-dtd;application/vnd.dolby.mlp;application/x-doom;application/vnd.dpgraph;audio/vnd.dra;application/vnd.dreamfactory;audio/vnd.dts;audio/vnd.dts.hd;imag/vnd.dwg;application/vnd.dynageo;application/ecmascript;application/vnd.ecowin.chart;image/vnd.fujixerox.edmics-mmr;image/vnd.fujixerox.edmics-rlc;application/exi;application/vnd.proteus.magazine;application/epub+zip;message/rfc82;application/vnd.enliven;application/vnd.is-xpr;image/vnd.xiff;application/vnd.xfdl;application/emma+xml;application/vnd.ezpix-album;application/vnd.ezpix-package;image/vnd.fst;video/vnd.fvt;image/vnd.fastbidsheet;application/vn.denovo.fcselayout-link;video/x-f4v;video/x-flv;image/vnd.fpx;image/vnd.net-fpx;text/vnd.fmi.flexstor;video/x-fli;application/vnd.fluxtime.clip;application/vnd.fdf;text/x-fortran;application/vnd.mif;application/vnd.framemaker;imae/x-freehand;application/vnd.fsc.weblaunch;application/vnd.frogans.fnc;application/vnd.frogans.ltf;application/vnd.fujixerox.ddd;application/vnd.fujixerox.docuworks;application/vnd.fujixerox.docuworks.binder;application/vnd.fujitu.oasys;application/vnd.fujitsu.oasys2;application/vnd.fujitsu.oasys3;application/vnd.fujitsu.oasysgp;application/vnd.fujitsu.oasysprs;application/x-futuresplash;application/vnd.fuzzysheet;image/g3fax;application/vnd.gmx;model/vn.gtw;application/vnd.genomatix.tuxedo;application/vnd.geogebra.file;application/vnd.geogebra.tool;model/vnd.gdl;application/vnd.geometry-explorer;application/vnd.geonext;application/vnd.geoplan;application/vnd.geospace;applicatio/x-font-ghostscript;application/x-font-bdf;application/x-gtar;application/x-texinfo;application/x-gnumeric;application/vnd.google-earth.kml+xml;application/vnd.google-earth.kmz;application/vnd.grafeq;image/gif;text/vnd.graphviz;aplication/vnd.groove-account;application/vnd.groove-help;application/vnd.groove-identity-message;application/vnd.groove-injector;application/vnd.groove-tool-message;application/vnd.groove-tool-template;application/vnd.groove-vcar;video/h261;video/h263;video/h264;application/vnd.hp-hpid;application/vnd.hp-hps;application/x-hdf;audio/vnd.rip;application/vnd.hbci;application/vnd.hp-jlyt;application/vnd.hp-pcl;application/vnd.hp-hpgl;application/vnd.yamaha.h-script;application/vnd.yamaha.hv-dic;application/vnd.yamaha.hv-voice;application/vnd.hydrostatix.sof-data;application/hyperstudio;application/vnd.hal+xml;text/html;application/vnd.ibm.rights-management;application/vnd.ibm.securecontainer;text/calendar;application/vnd.iccprofile;image/x-icon;application/vnd.igloader;image/ief;application/vnd.immervision-ivp;application/vnd.immervision-ivu;application/reginfo+xml;text/vnd.in3d.3dml;text/vnd.in3d.spot;mode/iges;application/vnd.intergeo;application/vnd.cinderella;application/vnd.intercon.formnet;application/vnd.isac.fcs;application/ipfix;application/pkix-cert;application/pkixcmp;application/pkix-crl;application/pkix-pkipath;applicaion/vnd.insors.igm;application/vnd.ipunplugged.rcprofile;application/vnd.irepository.package+xml;text/vnd.sun.j2me.app-descriptor;application/java-archive;application/java-vm;application/x-java-jnlp-file;application/java-serializd-object;text/x-java-source,java;application/javascript;application/json;application/vnd.joost.joda-archive;video/jpm;image/jpeg;video/jpeg;application/vnd.kahootz;application/vnd.chipnuts.karaoke-mmd;application/vnd.kde.karbon;aplication/vnd.kde.kchart;application/vnd.kde.kformula;application/vnd.kde.kivio;application/vnd.kde.kontour;application/vnd.kde.kpresenter;application/vnd.kde.kspread;application/vnd.kde.kword;application/vnd.kenameaapp;applicatin/vnd.kidspiration;application/vnd.kinar;application/vnd.kodak-descriptor;application/vnd.las.las+xml;application/x-latex;application/vnd.llamagraphics.life-balance.desktop;application/vnd.llamagraphics.life-balance.exchange+xml;application/vnd.jam;application/vnd.lotus-1-2-3;application/vnd.lotus-approach;application/vnd.lotus-freelance;application/vnd.lotus-notes;application/vnd.lotus-organizer;application/vnd.lotus-screencam;application/vnd.lotus-wordro;audio/vnd.lucent.voice;audio/x-mpegurl;video/x-m4v;application/mac-binhex40;application/vnd.macports.portpkg;application/vnd.osgeo.mapguide.package;application/marc;application/marcxml+xml;application/mxf;application/vnd.wolfrm.player;application/mathematica;application/mathml+xml;application/mbox;application/vnd.medcalcdata;application/mediaservercontrol+xml;application/vnd.mediastation.cdkey;application/vnd.mfer;application/vnd.mfmp;model/mesh;appliation/mads+xml;application/mets+xml;application/mods+xml;application/metalink4+xml;application/vnd.ms-powerpoint.template.macroenabled.12;application/vnd.ms-word.document.macroenabled.12;application/vnd.ms-word.template.macroenabed.12;application/vnd.mcd;application/vnd.micrografx.flo;application/vnd.micrografx.igx;application/vnd.eszigno3+xml;application/x-msaccess;video/x-ms-asf;application/x-msdownload;application/vnd.ms-artgalry;application/vnd.ms-ca-compressed;application/vnd.ms-ims;application/x-ms-application;application/x-msclip;image/vnd.ms-modi;application/vnd.ms-fontobject;application/vnd.ms-excel;application/vnd.ms-excel.addin.macroenabled.12;application/vnd.ms-excelsheet.binary.macroenabled.12;application/vnd.ms-excel.template.macroenabled.12;application/vnd.ms-excel.sheet.macroenabled.12;application/vnd.ms-htmlhelp;application/x-mscardfile;application/vnd.ms-lrm;application/x-msmediaview;aplication/x-msmoney;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.slide;application/vnd.openxmlformats-officedocument.presentationml.slideshw;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.openxmformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/x-msbinder;application/vnd.ms-officetheme;application/onenote;audio/vnd.ms-playready.media.pya;vdeo/vnd.ms-playready.media.pyv;application/vnd.ms-powerpoint;application/vnd.ms-powerpoint.addin.macroenabled.12;application/vnd.ms-powerpoint.slide.macroenabled.12;application/vnd.ms-powerpoint.presentation.macroenabled.12;appliation/vnd.ms-powerpoint.slideshow.macroenabled.12;application/vnd.ms-project;application/x-mspublisher;application/x-msschedule;application/x-silverlight-app;application/vnd.ms-pki.stl;application/vnd.ms-pki.seccat;application/vn.visio;video/x-ms-wm;audio/x-ms-wma;audio/x-ms-wax;video/x-ms-wmx;application/x-ms-wmd;application/vnd.ms-wpl;application/x-ms-wmz;video/x-ms-wmv;video/x-ms-wvx;application/x-msmetafile;application/x-msterminal;application/msword;application/x-mswrite;application/vnd.ms-works;application/x-ms-xbap;application/vnd.ms-xpsdocument;audio/midi;application/vnd.ibm.minipay;application/vnd.ibm.modcap;application/vnd.jcp.javame.midlet-rms;application/vnd.tmobile-ivetv;application/x-mobipocket-ebook;application/vnd.mobius.mbk;application/vnd.mobius.dis;application/vnd.mobius.plc;application/vnd.mobius.mqy;application/vnd.mobius.msl;application/vnd.mobius.txf;application/vnd.mobius.daf;tex/vnd.fly;application/vnd.mophun.certificate;application/vnd.mophun.application;video/mj2;audio/mpeg;video/vnd.mpegurl;video/mpeg;application/mp21;audio/mp4;video/mp4;application/mp4;application/vnd.apple.mpegurl;application/vnd.msician;application/vnd.muvee.style;application/xv+xml;application/vnd.nokia.n-gage.data;application/vnd.nokia.n-gage.symbian.install;application/x-dtbncx+xml;application/x-netcdf;application/vnd.neurolanguage.nlu;application/vnd.na;application/vnd.noblenet-directory;application/vnd.noblenet-sealer;application/vnd.noblenet-web;application/vnd.nokia.radio-preset;application/vnd.nokia.radio-presets;text/n3;application/vnd.novadigm.edm;application/vnd.novadim.edx;application/vnd.novadigm.ext;application/vnd.flographit;audio/vnd.nuera.ecelp4800;audio/vnd.nuera.ecelp7470;audio/vnd.nuera.ecelp9600;application/oda;application/ogg;audio/ogg;video/ogg;application/vnd.oma.dd2+xml;applicatin/vnd.oasis.opendocument.text-web;application/oebps-package+xml;application/vnd.intu.qbo;application/vnd.openofficeorg.extension;application/vnd.yamaha.openscoreformat;audio/webm;video/webm;application/vnd.oasis.opendocument.char;application/vnd.oasis.opendocument.chart-template;application/vnd.oasis.opendocument.database;application/vnd.oasis.opendocument.formula;application/vnd.oasis.opendocument.formula-template;application/vnd.oasis.opendocument.grapics;application/vnd.oasis.opendocument.graphics-template;application/vnd.oasis.opendocument.image;application/vnd.oasis.opendocument.image-template;application/vnd.oasis.opendocument.presentation;application/vnd.oasis.opendocumen.presentation-template;application/vnd.oasis.opendocument.spreadsheet;application/vnd.oasis.opendocument.spreadsheet-template;application/vnd.oasis.opendocument.text;application/vnd.oasis.opendocument.text-master;application/vnd.asis.opendocument.text-template;image/ktx;application/vnd.sun.xml.calc;application/vnd.sun.xml.calc.template;application/vnd.sun.xml.draw;application/vnd.sun.xml.draw.template;application/vnd.sun.xml.impress;application/vnd.sun.xl.impress.template;application/vnd.sun.xml.math;application/vnd.sun.xml.writer;application/vnd.sun.xml.writer.global;application/vnd.sun.xml.writer.template;application/x-font-otf;application/vnd.yamaha.openscoreformat.osfpvg+xml;application/vnd.osgi.dp;application/vnd.palm;text/x-pascal;application/vnd.pawaafile;application/vnd.hp-pclxl;application/vnd.picsel;image/x-pcx;image/vnd.adobe.photoshop;application/pics-rules;image/x-pict;application/x-chat;aplication/pkcs10;application/x-pkcs12;application/pkcs7-mime;application/pkcs7-signature;application/x-pkcs7-certreqresp;application/x-pkcs7-certificates;application/pkcs8;application/vnd.pocketlearn;image/x-portable-anymap;image/-portable-bitmap;application/x-font-pcf;application/font-tdpfr;application/x-chess-pgn;image/x-portable-graymap;image/png;image/x-portable-pixmap;application/pskc+xml;application/vnd.ctc-posml;application/postscript;application/xfont-type1;application/vnd.powerbuilder6;application/pgp-encrypted;application/pgp-signature;application/vnd.previewsystems.box;application/vnd.pvi.ptid1;application/pls+xml;application/vnd.pg.format;application/vnd.pg.osasli;tex/prs.lines.tag;application/x-font-linux-psf;application/vnd.publishare-delta-tree;application/vnd.pmi.widget;application/vnd.quark.quarkxpress;application/vnd.epson.esf;application/vnd.epson.msf;application/vnd.epson.ssf;applicaton/vnd.epson.quickanime;application/vnd.intu.qfx;video/quicktime;application/x-rar-compressed;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;application/rsd+xml;application/vnd.rn-realmedia;application/vnd.realvnc.bed;applicatin/vnd.recordare.musicxml;application/vnd.recordare.musicxml+xml;application/relax-ng-compact-syntax;application/vnd.data-vision.rdz;application/rdf+xml;application/vnd.cloanto.rp9;application/vnd.jisp;application/rtf;text/richtex;application/vnd.route66.link66+xml;application/rss+xml;application/shf+xml;application/vnd.sailingtracker.track;image/svg+xml;application/vnd.sus-calendar;application/sru+xml;application/set-payment-initiation;application/set-reistration-initiation;application/vnd.sema;application/vnd.semd;application/vnd.semf;application/vnd.seemail;application/x-font-snf;application/scvp-vp-request;application/scvp-vp-response;application/scvp-cv-request;application/svp-cv-response;application/sdp;text/x-setext;video/x-sgi-movie;application/vnd.shana.informed.formdata;application/vnd.shana.informed.formtemplate;application/vnd.shana.informed.interchange;application/vnd.shana.informed.package;application/thraud+xml;application/x-shar;image/x-rgb;application/vnd.epson.salt;application/vnd.accpac.simply.aso;application/vnd.accpac.simply.imp;application/vnd.simtech-mindmapper;application/vnd.commonspace;application/vnd.ymaha.smaf-audio;application/vnd.smaf;application/vnd.yamaha.smaf-phrase;application/vnd.smart.teacher;application/vnd.svd;application/sparql-query;application/sparql-results+xml;application/srgs;application/srgs+xml;application/sml+xml;application/vnd.koan;text/sgml;application/vnd.stardivision.calc;application/vnd.stardivision.draw;application/vnd.stardivision.impress;application/vnd.stardivision.math;application/vnd.stardivision.writer;application/vnd.tardivision.writer-global;application/vnd.stepmania.stepchart;application/x-stuffit;application/x-stuffitx;application/vnd.solent.sdkm+xml;application/vnd.olpc-sugar;audio/basic;application/vnd.wqd;application/vnd.symbian.install;application/smil+xml;application/vnd.syncml+xml;application/vnd.syncml.dm+wbxml;application/vnd.syncml.dm+xml;application/x-sv4cpio;application/x-sv4crc;application/sbml+xml;text/tab-separated-values;image/tiff;application/vnd.to.intent-module-archive;application/x-tar;application/x-tcl;application/x-tex;application/x-tex-tfm;application/tei+xml;text/plain;application/vnd.spotfire.dxp;application/vnd.spotfire.sfs;application/timestamped-data;applicationvnd.trid.tpt;application/vnd.triscape.mxs;text/troff;application/vnd.trueapp;application/x-font-ttf;text/turtle;application/vnd.umajin;application/vnd.uoml+xml;application/vnd.unity;application/vnd.ufdl;text/uri-list;application/nd.uiq.theme;application/x-ustar;text/x-uuencode;text/x-vcalendar;text/x-vcard;application/x-cdlink;application/vnd.vsf;model/vrml;application/vnd.vcx;model/vnd.mts;model/vnd.vtu;application/vnd.visionary;video/vnd.vivo;applicatin/ccxml+xml,;application/voicexml+xml;application/x-wais-source;application/vnd.wap.wbxml;image/vnd.wap.wbmp;audio/x-wav;application/davmount+xml;application/x-font-woff;application/wspolicy+xml;image/webp;application/vnd.webturb;application/widget;application/winhlp;text/vnd.wap.wml;text/vnd.wap.wmlscript;application/vnd.wap.wmlscriptc;application/vnd.wordperfect;application/vnd.wt.stf;application/wsdl+xml;image/x-xbitmap;image/x-xpixmap;image/x-xwindowump;application/x-x509-ca-cert;application/x-xfig;application/xhtml+xml;application/xml;application/xcap-diff+xml;application/xenc+xml;application/patch-ops-error+xml;application/resource-lists+xml;application/rls-services+xml;aplication/resource-lists-diff+xml;application/xslt+xml;application/xop+xml;application/x-xpinstall;application/xspf+xml;application/vnd.mozilla.xul+xml;chemical/x-xyz;text/yaml;application/yang;application/yin+xml;application/vnd.ul;application/zip;application/vnd.handheld-entertainment+xml;application/vnd.zzazz.deck+xml') # noqa
browser = webdriver.Firefox(firefox_profile=profile, options=options)
browser.implicitly_wait(10)
browser.set_window_size(1920, 1080)
return browser
......
......@@ -36,7 +36,7 @@ class UserAccountFactory(DjangoModelFactory):
role = models.UserAccount.TUTOR
fullname = fake.name
username = fake.user_name
username = factory.Sequence(lambda n: f"{fake.user_name()}-{n}")
password = factory.PostGenerationMethodCall('set_password', 'redrum-is-murder-reversed')
......@@ -45,7 +45,7 @@ class StudentInfoFactory(DjangoModelFactory):
model = models.StudentInfo
exam = factory.SubFactory(ExamTypeFactory)
user = factory.SubFactory(UserAccountFactory)
user = factory.SubFactory(UserAccountFactory, role=models.UserAccount.STUDENT)
class TestFactory(DjangoModelFactory):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment