mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-10-30 22:27:52 +00:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			3572-fixed
			...
			path-bluep
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | db7f7f0768 | ||
|   | 2a91c1f8d1 | ||
|   | 0131de3e3a | ||
|   | edefdcb743 | 
| @@ -138,7 +138,7 @@ def construct_blueprint(datastore: ChangeDetectionStore): | ||||
|         return send_from_directory(os.path.abspath(datastore.datastore_path), filename, as_attachment=True) | ||||
|  | ||||
|     @login_optionally_required | ||||
|     @backups_blueprint.route("/", methods=['GET']) | ||||
|     @backups_blueprint.route("", methods=['GET']) | ||||
|     def index(): | ||||
|         backups = find_backups() | ||||
|         output = render_template("overview.html", | ||||
|   | ||||
| @@ -27,7 +27,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|                     update_q.put(queuedWatchMetaData.PrioritizedItem(priority=1, item={'uuid': uuid})) | ||||
|  | ||||
|                 if len(importer_handler.remaining_data) == 0: | ||||
|                     return redirect(url_for('index')) | ||||
|                     return redirect(url_for('watchlist.index')) | ||||
|                 else: | ||||
|                     remaining_urls = importer_handler.remaining_data | ||||
|  | ||||
|   | ||||
| @@ -20,13 +20,13 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q: PriorityQueue | ||||
|         datastore.data['watching'][uuid]['processor'] = 'restock_diff' | ||||
|         datastore.data['watching'][uuid].clear_watch() | ||||
|         update_q.put(queuedWatchMetaData.PrioritizedItem(priority=1, item={'uuid': uuid})) | ||||
|         return redirect(url_for("index")) | ||||
|         return redirect(url_for("watchlist.index")) | ||||
|  | ||||
|     @login_required | ||||
|     @price_data_follower_blueprint.route("/<string:uuid>/reject", methods=['GET']) | ||||
|     def reject(uuid): | ||||
|         datastore.data['watching'][uuid]['track_ldjson_price_data'] = PRICE_DATA_TRACK_REJECT | ||||
|         return redirect(url_for("index")) | ||||
|         return redirect(url_for("watchlist.index")) | ||||
|  | ||||
|  | ||||
|     return price_data_follower_blueprint | ||||
|   | ||||
| @@ -13,8 +13,7 @@ def construct_blueprint(datastore: ChangeDetectionStore): | ||||
|      | ||||
|     # Import the login decorator if needed | ||||
|     # from changedetectionio.auth_decorator import login_optionally_required | ||||
|  | ||||
|     @rss_blueprint.route("/", methods=['GET']) | ||||
|     @rss_blueprint.route("", methods=['GET']) | ||||
|     def feed(): | ||||
|         now = time.time() | ||||
|         # Always requires token set | ||||
|   | ||||
| @@ -13,7 +13,7 @@ from changedetectionio.auth_decorator import login_optionally_required | ||||
| def construct_blueprint(datastore: ChangeDetectionStore): | ||||
|     settings_blueprint = Blueprint('settings', __name__, template_folder="templates") | ||||
|  | ||||
|     @settings_blueprint.route("/", methods=['GET', "POST"]) | ||||
|     @settings_blueprint.route("", methods=['GET', "POST"]) | ||||
|     @login_optionally_required | ||||
|     def settings_page(): | ||||
|         from changedetectionio import forms | ||||
| @@ -74,7 +74,7 @@ def construct_blueprint(datastore: ChangeDetectionStore): | ||||
|                     datastore.needs_write_urgent = True | ||||
|                     flash("Password protection enabled.", 'notice') | ||||
|                     flask_login.logout_user() | ||||
|                     return redirect(url_for('index')) | ||||
|                     return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|                 datastore.needs_write_urgent = True | ||||
|                 flash("Settings updated.") | ||||
|   | ||||
| @@ -299,7 +299,7 @@ nav | ||||
|             <div id="actions"> | ||||
|                 <div class="pure-control-group"> | ||||
|                     {{ render_button(form.save_button) }} | ||||
|                     <a href="{{url_for('index')}}" class="pure-button button-small button-cancel">Back</a> | ||||
|                     <a href="{{url_for('watchlist.index')}}" class="pure-button button-small button-cancel">Back</a> | ||||
|                     <a href="{{url_for('ui.clear_all_history')}}" class="pure-button button-small button-error">Clear Snapshot History</a> | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
| @@ -47,7 +47,7 @@ | ||||
|                     <a class="link-mute state-{{'on' if tag.notification_muted else 'off'}}" href="{{url_for('tags.mute', uuid=tag.uuid)}}"><img src="{{url_for('static_content', group='images', filename='bell-off.svg')}}" alt="Mute notifications" title="Mute notifications" class="icon icon-mute" ></a> | ||||
|                 </td> | ||||
|                 <td>{{ "{:,}".format(tag_count[uuid]) if uuid in tag_count else 0 }}</td> | ||||
|                 <td class="title-col inline"> <a href="{{url_for('index', tag=uuid) }}">{{ tag.title }}</a></td> | ||||
|                 <td class="title-col inline"> <a href="{{url_for('watchlist.index', tag=uuid) }}">{{ tag.title }}</a></td> | ||||
|                 <td> | ||||
|                     <a class="pure-button pure-button-primary" href="{{ url_for('tags.form_tag_edit', uuid=uuid) }}">Edit</a>  | ||||
|                     <a class="pure-button pure-button-primary" href="{{ url_for('tags.delete', uuid=uuid) }}" title="Deletes and removes tag">Delete</a> | ||||
|   | ||||
| @@ -36,7 +36,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|         else: | ||||
|             flash("Cleared snapshot history for watch {}".format(uuid)) | ||||
|  | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|     @ui_blueprint.route("/clear_history", methods=['GET', 'POST']) | ||||
|     @login_optionally_required | ||||
| @@ -52,7 +52,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|             else: | ||||
|                 flash('Incorrect confirmation text.', 'error') | ||||
|  | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         output = render_template("clear_all_history.html") | ||||
|         return output | ||||
| @@ -68,7 +68,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|                 continue | ||||
|             datastore.set_last_viewed(watch_uuid, int(time.time())) | ||||
|  | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|     @ui_blueprint.route("/delete", methods=['GET']) | ||||
|     @login_optionally_required | ||||
| @@ -77,7 +77,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|  | ||||
|         if uuid != 'all' and not uuid in datastore.data['watching'].keys(): | ||||
|             flash('The watch by UUID {} does not exist.'.format(uuid), 'error') | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         # More for testing, possible to return the first/only | ||||
|         if uuid == 'first': | ||||
| @@ -85,7 +85,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|         datastore.delete(uuid) | ||||
|         flash('Deleted.') | ||||
|  | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|     @ui_blueprint.route("/clone", methods=['GET']) | ||||
|     @login_optionally_required | ||||
| @@ -101,7 +101,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|                 update_q.put(queuedWatchMetaData.PrioritizedItem(priority=5, item={'uuid': new_uuid})) | ||||
|             flash('Cloned.') | ||||
|  | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|     @ui_blueprint.route("/checknow", methods=['GET']) | ||||
|     @login_optionally_required | ||||
| @@ -143,7 +143,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|         if i == 0: | ||||
|             flash("No watches available to recheck.") | ||||
|  | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|     @ui_blueprint.route("/form/checkbox-operations", methods=['POST']) | ||||
|     @login_optionally_required | ||||
| @@ -244,7 +244,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|  | ||||
|             flash(f"{len(uuids)} watches were tagged") | ||||
|  | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|  | ||||
|     @ui_blueprint.route("/share-url/<string:uuid>", methods=['GET']) | ||||
| @@ -296,6 +296,6 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, running_updat | ||||
|             logger.error(f"Error sharing -{str(e)}") | ||||
|             flash(f"Could not share, something went wrong while communicating with the share server - {str(e)}", 'error') | ||||
|  | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|     return ui_blueprint | ||||
| @@ -32,14 +32,14 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|         # More for testing, possible to return the first/only | ||||
|         if not datastore.data['watching'].keys(): | ||||
|             flash("No watches to edit", "error") | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         if uuid == 'first': | ||||
|             uuid = list(datastore.data['watching'].keys()).pop() | ||||
|  | ||||
|         if not uuid in datastore.data['watching']: | ||||
|             flash("No watch with the UUID %s found." % (uuid), "error") | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         switch_processor = request.args.get('switch_processor') | ||||
|         if switch_processor: | ||||
| @@ -66,7 +66,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|         processor_classes = next((tpl for tpl in processors.find_processors() if tpl[1] == processor_name), None) | ||||
|         if not processor_classes: | ||||
|             flash(f"Cannot load the edit form for processor/plugin '{processor_classes[1]}', plugin missing?", 'error') | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         parent_module = processors.get_parent_module(processor_classes[0]) | ||||
|  | ||||
| @@ -207,7 +207,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|             if request.args.get("next") and request.args.get("next") == 'diff': | ||||
|                 return redirect(url_for('ui.ui_views.diff_history_page', uuid=uuid)) | ||||
|  | ||||
|             return redirect(url_for('index', tag=request.args.get("tag",''))) | ||||
|             return redirect(url_for('watchlist.index', tag=request.args.get("tag",''))) | ||||
|  | ||||
|         else: | ||||
|             if request.method == 'POST' and not form.validate(): | ||||
|   | ||||
| @@ -37,7 +37,7 @@ | ||||
|         </div> | ||||
|         <br /> | ||||
|         <div class="pure-control-group"> | ||||
|           <a href="{{url_for('index')}}" class="pure-button button-cancel" | ||||
|           <a href="{{url_for('watchlist.index')}}" class="pure-button button-cancel" | ||||
|             >Cancel</a | ||||
|           > | ||||
|         </div> | ||||
|   | ||||
| @@ -26,7 +26,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|             watch = datastore.data['watching'][uuid] | ||||
|         except KeyError: | ||||
|             flash("No history found for the specified link, bad link?", "error") | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         system_uses_webdriver = datastore.data['settings']['application']['fetch_backend'] == 'html_webdriver' | ||||
|         extra_stylesheets = [url_for('static_content', group='styles', filename='diff.css')] | ||||
| @@ -91,7 +91,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|             watch = datastore.data['watching'][uuid] | ||||
|         except KeyError: | ||||
|             flash("No history found for the specified link, bad link?", "error") | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         # For submission of requesting an extract | ||||
|         extract_form = forms.extractDataForm(request.form) | ||||
| @@ -119,7 +119,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|  | ||||
|         if len(dates) < 2: | ||||
|             flash("Not enough saved change detection snapshots to produce a report.", "error") | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         # Save the current newest history as the most recently viewed | ||||
|         datastore.set_last_viewed(uuid, time.time()) | ||||
| @@ -196,7 +196,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|         if not form.validate(): | ||||
|             for widget, l in form.errors.items(): | ||||
|                 flash(','.join(l), 'error') | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         url = request.form.get('url').strip() | ||||
|         if datastore.url_exists(url): | ||||
| @@ -215,6 +215,6 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe | ||||
|                 update_q.put(queuedWatchMetaData.PrioritizedItem(priority=1, item={'uuid': new_uuid})) | ||||
|                 flash("Watch added.") | ||||
|  | ||||
|         return redirect(url_for('index', tag=request.args.get('tag',''))) | ||||
|         return redirect(url_for('watchlist.index', tag=request.args.get('tag',''))) | ||||
|  | ||||
|     return views_blueprint | ||||
							
								
								
									
										114
									
								
								changedetectionio/blueprint/watchlist/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								changedetectionio/blueprint/watchlist/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| import flask_login | ||||
| import os | ||||
| import time | ||||
| import timeago | ||||
|  | ||||
| from flask import Blueprint, request, make_response, render_template, redirect, url_for, flash, session | ||||
| from flask_login import current_user | ||||
| from flask_paginate import Pagination, get_page_parameter | ||||
|  | ||||
| from changedetectionio import forms | ||||
| from changedetectionio.store import ChangeDetectionStore | ||||
| from changedetectionio.auth_decorator import login_optionally_required | ||||
| from changedetectionio.strtobool import strtobool | ||||
|  | ||||
| def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMetaData): | ||||
|     watchlist_blueprint = Blueprint('watchlist', __name__, template_folder="templates") | ||||
|      | ||||
|     @watchlist_blueprint.route("/", methods=['GET']) | ||||
|     @login_optionally_required | ||||
|     def index(): | ||||
|         active_tag_req = request.args.get('tag', '').lower().strip() | ||||
|         active_tag_uuid = active_tag = None | ||||
|  | ||||
|         # Be sure limit_tag is a uuid | ||||
|         if active_tag_req: | ||||
|             for uuid, tag in datastore.data['settings']['application'].get('tags', {}).items(): | ||||
|                 if active_tag_req == tag.get('title', '').lower().strip() or active_tag_req == uuid: | ||||
|                     active_tag = tag | ||||
|                     active_tag_uuid = uuid | ||||
|                     break | ||||
|  | ||||
|         # Redirect for the old rss path which used the /?rss=true | ||||
|         if request.args.get('rss'): | ||||
|             return redirect(url_for('rss.feed', tag=active_tag_uuid)) | ||||
|  | ||||
|         op = request.args.get('op') | ||||
|         if op: | ||||
|             uuid = request.args.get('uuid') | ||||
|             if op == 'pause': | ||||
|                 datastore.data['watching'][uuid].toggle_pause() | ||||
|             elif op == 'mute': | ||||
|                 datastore.data['watching'][uuid].toggle_mute() | ||||
|  | ||||
|             datastore.needs_write = True | ||||
|             return redirect(url_for('watchlist.index', tag = active_tag_uuid)) | ||||
|  | ||||
|         # Sort by last_changed and add the uuid which is usually the key.. | ||||
|         sorted_watches = [] | ||||
|         with_errors = request.args.get('with_errors') == "1" | ||||
|         errored_count = 0 | ||||
|         search_q = request.args.get('q').strip().lower() if request.args.get('q') else False | ||||
|         for uuid, watch in datastore.data['watching'].items(): | ||||
|             if with_errors and not watch.get('last_error'): | ||||
|                 continue | ||||
|  | ||||
|             if active_tag_uuid and not active_tag_uuid in watch['tags']: | ||||
|                     continue | ||||
|             if watch.get('last_error'): | ||||
|                 errored_count += 1 | ||||
|  | ||||
|             if search_q: | ||||
|                 if (watch.get('title') and search_q in watch.get('title').lower()) or search_q in watch.get('url', '').lower(): | ||||
|                     sorted_watches.append(watch) | ||||
|                 elif watch.get('last_error') and search_q in watch.get('last_error').lower(): | ||||
|                     sorted_watches.append(watch) | ||||
|             else: | ||||
|                 sorted_watches.append(watch) | ||||
|  | ||||
|         form = forms.quickWatchForm(request.form) | ||||
|         page = request.args.get(get_page_parameter(), type=int, default=1) | ||||
|         total_count = len(sorted_watches) | ||||
|  | ||||
|         pagination = Pagination(page=page, | ||||
|                                 total=total_count, | ||||
|                                 per_page=datastore.data['settings']['application'].get('pager_size', 50), css_framework="semantic") | ||||
|  | ||||
|         sorted_tags = sorted(datastore.data['settings']['application'].get('tags').items(), key=lambda x: x[1]['title']) | ||||
|         output = render_template( | ||||
|             "watch-overview.html", | ||||
|                                  # Don't link to hosting when we're on the hosting environment | ||||
|                                  active_tag=active_tag, | ||||
|                                  active_tag_uuid=active_tag_uuid, | ||||
|                                  app_rss_token=datastore.data['settings']['application'].get('rss_access_token'), | ||||
|                                  datastore=datastore, | ||||
|                                  errored_count=errored_count, | ||||
|                                  form=form, | ||||
|                                  guid=datastore.data['app_guid'], | ||||
|                                  has_proxies=datastore.proxy_list, | ||||
|                                  has_unviewed=datastore.has_unviewed, | ||||
|                                  hosted_sticky=os.getenv("SALTED_PASS", False) == False, | ||||
|                                  pagination=pagination, | ||||
|                                  queued_uuids=[q_uuid.item['uuid'] for q_uuid in update_q.queue], | ||||
|                                  search_q=request.args.get('q','').strip(), | ||||
|                                  sort_attribute=request.args.get('sort') if request.args.get('sort') else request.cookies.get('sort'), | ||||
|                                  sort_order=request.args.get('order') if request.args.get('order') else request.cookies.get('order'), | ||||
|                                  system_default_fetcher=datastore.data['settings']['application'].get('fetch_backend'), | ||||
|                                  tags=sorted_tags, | ||||
|                                  watches=sorted_watches | ||||
|                                  ) | ||||
|  | ||||
|         if session.get('share-link'): | ||||
|             del(session['share-link']) | ||||
|  | ||||
|         resp = make_response(output) | ||||
|  | ||||
|         # The template can run on cookie or url query info | ||||
|         if request.args.get('sort'): | ||||
|             resp.set_cookie('sort', request.args.get('sort')) | ||||
|         if request.args.get('order'): | ||||
|             resp.set_cookie('order', request.args.get('order')) | ||||
|  | ||||
|         return resp | ||||
|          | ||||
|     return watchlist_blueprint | ||||
| @@ -46,12 +46,12 @@ | ||||
|     {% endif %} | ||||
|     {% if search_q %}<div id="search-result-info">Searching "<strong><i>{{search_q}}</i></strong>"</div>{% endif %} | ||||
|     <div> | ||||
|         <a href="{{url_for('index')}}" class="pure-button button-tag {{'active' if not active_tag_uuid }}">All</a> | ||||
|         <a href="{{url_for('watchlist.index')}}" class="pure-button button-tag {{'active' if not active_tag_uuid }}">All</a> | ||||
| 
 | ||||
|     <!-- tag list --> | ||||
|     {% for uuid, tag in tags %} | ||||
|         {% if tag != "" %} | ||||
|             <a href="{{url_for('index', tag=uuid) }}" class="pure-button button-tag {{'active' if active_tag_uuid == uuid }}">{{ tag.title }}</a> | ||||
|             <a href="{{url_for('watchlist.index', tag=uuid) }}" class="pure-button button-tag {{'active' if active_tag_uuid == uuid }}">{{ tag.title }}</a> | ||||
|         {% endif %} | ||||
|     {% endfor %} | ||||
|     </div> | ||||
| @@ -72,14 +72,14 @@ | ||||
|             <tr> | ||||
|                 {% set link_order = "desc" if sort_order  == 'asc' else "asc" %} | ||||
|                 {% set arrow_span = "" %} | ||||
|                 <th><input style="vertical-align: middle" type="checkbox" id="check-all" > <a class="{{ 'active '+link_order if sort_attribute == 'date_created' else 'inactive' }}"  href="{{url_for('index', sort='date_created', order=link_order, tag=active_tag_uuid)}}"># <span class='arrow {{link_order}}'></span></a></th> | ||||
|                 <th><input style="vertical-align: middle" type="checkbox" id="check-all" > <a class="{{ 'active '+link_order if sort_attribute == 'date_created' else 'inactive' }}"  href="{{url_for('watchlist.index', sort='date_created', order=link_order, tag=active_tag_uuid)}}"># <span class='arrow {{link_order}}'></span></a></th> | ||||
|                 <th class="empty-cell"></th> | ||||
|                 <th><a class="{{ 'active '+link_order if sort_attribute == 'label' else 'inactive' }}" href="{{url_for('index', sort='label', order=link_order, tag=active_tag_uuid)}}">Website <span class='arrow {{link_order}}'></span></a></th> | ||||
|                 <th><a class="{{ 'active '+link_order if sort_attribute == 'label' else 'inactive' }}" href="{{url_for('watchlist.index', sort='label', order=link_order, tag=active_tag_uuid)}}">Website <span class='arrow {{link_order}}'></span></a></th> | ||||
|              {% if any_has_restock_price_processor %} | ||||
|                 <th>Restock & Price</th> | ||||
|              {% endif %} | ||||
|                 <th><a class="{{ 'active '+link_order if sort_attribute == 'last_checked' else 'inactive' }}" href="{{url_for('index', sort='last_checked', order=link_order, tag=active_tag_uuid)}}"><span class="hide-on-mobile">Last</span> Checked <span class='arrow {{link_order}}'></span></a></th> | ||||
|                 <th><a class="{{ 'active '+link_order if sort_attribute == 'last_changed' else 'inactive' }}" href="{{url_for('index', sort='last_changed', order=link_order, tag=active_tag_uuid)}}"><span class="hide-on-mobile">Last</span> Changed <span class='arrow {{link_order}}'></span></a></th> | ||||
|                 <th><a class="{{ 'active '+link_order if sort_attribute == 'last_checked' else 'inactive' }}" href="{{url_for('watchlist.index', sort='last_checked', order=link_order, tag=active_tag_uuid)}}"><span class="hide-on-mobile">Last</span> Checked <span class='arrow {{link_order}}'></span></a></th> | ||||
|                 <th><a class="{{ 'active '+link_order if sort_attribute == 'last_changed' else 'inactive' }}" href="{{url_for('watchlist.index', sort='last_changed', order=link_order, tag=active_tag_uuid)}}"><span class="hide-on-mobile">Last</span> Changed <span class='arrow {{link_order}}'></span></a></th> | ||||
|                 <th class="empty-cell"></th> | ||||
|             </tr> | ||||
|             </thead> | ||||
| @@ -104,12 +104,12 @@ | ||||
|                 <td class="inline checkbox-uuid" ><input name="uuids"  type="checkbox" value="{{ watch.uuid}} " > <span>{{ loop.index+pagination.skip }}</span></td> | ||||
|                 <td class="inline watch-controls"> | ||||
|                     {% if not watch.paused %} | ||||
|                     <a class="state-off" href="{{url_for('index', op='pause', uuid=watch.uuid, tag=active_tag_uuid)}}"><img src="{{url_for('static_content', group='images', filename='pause.svg')}}" alt="Pause checks" title="Pause checks" class="icon icon-pause" ></a> | ||||
|                     <a class="state-off" href="{{url_for('watchlist.index', op='pause', uuid=watch.uuid, tag=active_tag_uuid)}}"><img src="{{url_for('static_content', group='images', filename='pause.svg')}}" alt="Pause checks" title="Pause checks" class="icon icon-pause" ></a> | ||||
|                     {% else %} | ||||
|                     <a class="state-on" href="{{url_for('index', op='pause', uuid=watch.uuid, tag=active_tag_uuid)}}"><img src="{{url_for('static_content', group='images', filename='play.svg')}}" alt="UnPause checks" title="UnPause checks" class="icon icon-unpause" ></a> | ||||
|                     <a class="state-on" href="{{url_for('watchlist.index', op='pause', uuid=watch.uuid, tag=active_tag_uuid)}}"><img src="{{url_for('static_content', group='images', filename='play.svg')}}" alt="UnPause checks" title="UnPause checks" class="icon icon-unpause" ></a> | ||||
|                     {% endif %} | ||||
|                     {% set mute_label = 'UnMute notification' if watch.notification_muted else 'Mute notification' %} | ||||
|                     <a class="link-mute state-{{'on' if watch.notification_muted else 'off'}}" href="{{url_for('index', op='mute', uuid=watch.uuid, tag=active_tag_uuid)}}"><img src="{{url_for('static_content', group='images', filename='bell-off.svg')}}" alt="{{ mute_label }}" title="{{ mute_label }}" class="icon icon-mute" ></a> | ||||
|                     <a class="link-mute state-{{'on' if watch.notification_muted else 'off'}}" href="{{url_for('watchlist.index', op='mute', uuid=watch.uuid, tag=active_tag_uuid)}}"><img src="{{url_for('static_content', group='images', filename='bell-off.svg')}}" alt="{{ mute_label }}" title="{{ mute_label }}" class="icon icon-mute" ></a> | ||||
|                 </td> | ||||
|                 <td class="title-col inline">{{watch.title if watch.title is not none and watch.title|length > 0 else watch.url}} | ||||
|                     <a class="external" target="_blank" rel="noopener" href="{{ watch.link.replace('source:','') }}"></a> | ||||
| @@ -210,7 +210,7 @@ | ||||
|         <ul id="post-list-buttons"> | ||||
|             {% if errored_count %} | ||||
|             <li> | ||||
|                 <a href="{{url_for('index', with_errors=1, tag=request.args.get('tag')) }}" class="pure-button button-tag button-error ">With errors ({{ errored_count }})</a> | ||||
|                 <a href="{{url_for('watchlist.index', with_errors=1, tag=request.args.get('tag')) }}" class="pure-button button-tag button-error ">With errors ({{ errored_count }})</a> | ||||
|             </li> | ||||
|             {% endif %} | ||||
|             {% if has_unviewed %} | ||||
| @@ -228,7 +228,7 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|  | ||||
|         if has_password_enabled and not flask_login.current_user.is_authenticated: | ||||
|             # Permitted | ||||
|             if request.endpoint and 'static_content' in request.endpoint and request.view_args and request.view_args.get('group') == 'styles': | ||||
|             if request.endpoint and request.endpoint == 'static_content' and request.view_args and request.view_args.get('group') in ['styles', 'js', 'images', 'favicons']: | ||||
|                 return None | ||||
|             # Permitted | ||||
|             elif request.endpoint and 'login' in request.endpoint: | ||||
| @@ -287,12 +287,12 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|     @login_manager.unauthorized_handler | ||||
|     def unauthorized_handler(): | ||||
|         flash("You must be logged in, please log in.", 'error') | ||||
|         return redirect(url_for('login', next=url_for('index'))) | ||||
|         return redirect(url_for('login', next=url_for('watchlist.index'))) | ||||
|  | ||||
|     @app.route('/logout') | ||||
|     def logout(): | ||||
|         flask_login.logout_user() | ||||
|         return redirect(url_for('index')) | ||||
|         return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|     # https://github.com/pallets/flask/blob/93dd1709d05a1cf0e886df6223377bdab3b077fb/examples/tutorial/flaskr/__init__.py#L39 | ||||
|     # You can divide up the stuff like this | ||||
| @@ -302,7 +302,7 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|         if request.method == 'GET': | ||||
|             if flask_login.current_user.is_authenticated: | ||||
|                 flash("Already logged in") | ||||
|                 return redirect(url_for("index")) | ||||
|                 return redirect(url_for("watchlist.index")) | ||||
|  | ||||
|             output = render_template("login.html") | ||||
|             return output | ||||
| @@ -319,13 +319,13 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|             # It's more reliable and safe to ignore the 'next' redirect | ||||
|             # When we used... | ||||
|             # next = request.args.get('next') | ||||
|             # return redirect(next or url_for('index')) | ||||
|             # return redirect(next or url_for('watchlist.index')) | ||||
|             # We would sometimes get login loop errors on sites hosted in sub-paths | ||||
|  | ||||
|             # note for the future: | ||||
|             #            if not is_safe_url(next): | ||||
|             #                return flask.abort(400) | ||||
|             return redirect(url_for('index')) | ||||
|             return redirect(url_for('watchlist.index')) | ||||
|  | ||||
|         else: | ||||
|             flash('Incorrect password', 'error') | ||||
| @@ -338,110 +338,8 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|         if os.getenv('USE_X_SETTINGS') and 'X-Forwarded-Prefix' in request.headers: | ||||
|             app.config['REMEMBER_COOKIE_PATH'] = request.headers['X-Forwarded-Prefix'] | ||||
|             app.config['SESSION_COOKIE_PATH'] = request.headers['X-Forwarded-Prefix'] | ||||
|  | ||||
|         return None | ||||
|  | ||||
|  | ||||
|     @app.route("/", methods=['GET']) | ||||
|     @login_optionally_required | ||||
|     def index(): | ||||
|         global datastore | ||||
|         from changedetectionio import forms | ||||
|  | ||||
|         active_tag_req = request.args.get('tag', '').lower().strip() | ||||
|         active_tag_uuid = active_tag = None | ||||
|  | ||||
|         # Be sure limit_tag is a uuid | ||||
|         if active_tag_req: | ||||
|             for uuid, tag in datastore.data['settings']['application'].get('tags', {}).items(): | ||||
|                 if active_tag_req == tag.get('title', '').lower().strip() or active_tag_req == uuid: | ||||
|                     active_tag = tag | ||||
|                     active_tag_uuid = uuid | ||||
|                     break | ||||
|  | ||||
|  | ||||
|         # Redirect for the old rss path which used the /?rss=true | ||||
|         if request.args.get('rss'): | ||||
|             return redirect(url_for('rss.feed', tag=active_tag_uuid)) | ||||
|  | ||||
|         op = request.args.get('op') | ||||
|         if op: | ||||
|             uuid = request.args.get('uuid') | ||||
|             if op == 'pause': | ||||
|                 datastore.data['watching'][uuid].toggle_pause() | ||||
|             elif op == 'mute': | ||||
|                 datastore.data['watching'][uuid].toggle_mute() | ||||
|  | ||||
|             datastore.needs_write = True | ||||
|             return redirect(url_for('index', tag = active_tag_uuid)) | ||||
|  | ||||
|         # Sort by last_changed and add the uuid which is usually the key.. | ||||
|         sorted_watches = [] | ||||
|         with_errors = request.args.get('with_errors') == "1" | ||||
|         errored_count = 0 | ||||
|         search_q = request.args.get('q').strip().lower() if request.args.get('q') else False | ||||
|         for uuid, watch in datastore.data['watching'].items(): | ||||
|             if with_errors and not watch.get('last_error'): | ||||
|                 continue | ||||
|  | ||||
|             if active_tag_uuid and not active_tag_uuid in watch['tags']: | ||||
|                     continue | ||||
|             if watch.get('last_error'): | ||||
|                 errored_count += 1 | ||||
|  | ||||
|             if search_q: | ||||
|                 if (watch.get('title') and search_q in watch.get('title').lower()) or search_q in watch.get('url', '').lower(): | ||||
|                     sorted_watches.append(watch) | ||||
|                 elif watch.get('last_error') and search_q in watch.get('last_error').lower(): | ||||
|                     sorted_watches.append(watch) | ||||
|             else: | ||||
|                 sorted_watches.append(watch) | ||||
|  | ||||
|         form = forms.quickWatchForm(request.form) | ||||
|         page = request.args.get(get_page_parameter(), type=int, default=1) | ||||
|         total_count = len(sorted_watches) | ||||
|  | ||||
|         pagination = Pagination(page=page, | ||||
|                                 total=total_count, | ||||
|                                 per_page=datastore.data['settings']['application'].get('pager_size', 50), css_framework="semantic") | ||||
|  | ||||
|         sorted_tags = sorted(datastore.data['settings']['application'].get('tags').items(), key=lambda x: x[1]['title']) | ||||
|         output = render_template( | ||||
|             "watch-overview.html", | ||||
|                                  # Don't link to hosting when we're on the hosting environment | ||||
|                                  active_tag=active_tag, | ||||
|                                  active_tag_uuid=active_tag_uuid, | ||||
|                                  app_rss_token=datastore.data['settings']['application'].get('rss_access_token'), | ||||
|                                  datastore=datastore, | ||||
|                                  errored_count=errored_count, | ||||
|                                  form=form, | ||||
|                                  guid=datastore.data['app_guid'], | ||||
|                                  has_proxies=datastore.proxy_list, | ||||
|                                  has_unviewed=datastore.has_unviewed, | ||||
|                                  hosted_sticky=os.getenv("SALTED_PASS", False) == False, | ||||
|                                  pagination=pagination, | ||||
|                                  queued_uuids=[q_uuid.item['uuid'] for q_uuid in update_q.queue], | ||||
|                                  search_q=request.args.get('q','').strip(), | ||||
|                                  sort_attribute=request.args.get('sort') if request.args.get('sort') else request.cookies.get('sort'), | ||||
|                                  sort_order=request.args.get('order') if request.args.get('order') else request.cookies.get('order'), | ||||
|                                  system_default_fetcher=datastore.data['settings']['application'].get('fetch_backend'), | ||||
|                                  tags=sorted_tags, | ||||
|                                  watches=sorted_watches | ||||
|                                  ) | ||||
|  | ||||
|         if session.get('share-link'): | ||||
|             del(session['share-link']) | ||||
|  | ||||
|         resp = make_response(output) | ||||
|  | ||||
|         # The template can run on cookie or url query info | ||||
|         if request.args.get('sort'): | ||||
|             resp.set_cookie('sort', request.args.get('sort')) | ||||
|         if request.args.get('order'): | ||||
|             resp.set_cookie('order', request.args.get('order')) | ||||
|  | ||||
|         return resp | ||||
|  | ||||
|     @app.route("/static/<string:group>/<string:filename>", methods=['GET']) | ||||
|     def static_content(group, filename): | ||||
|         from flask import make_response | ||||
| @@ -529,10 +427,13 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|  | ||||
|     import changedetectionio.blueprint.rss as rss | ||||
|     app.register_blueprint(rss.construct_blueprint(datastore), url_prefix='/rss') | ||||
|      | ||||
|  | ||||
|     # watchlist UI buttons etc | ||||
|     import changedetectionio.blueprint.ui as ui | ||||
|     app.register_blueprint(ui.construct_blueprint(datastore, update_q, running_update_threads, queuedWatchMetaData)) | ||||
|  | ||||
|     import changedetectionio.blueprint.watchlist as watchlist | ||||
|     app.register_blueprint(watchlist.construct_blueprint(datastore=datastore, update_q=update_q, queuedWatchMetaData=queuedWatchMetaData), url_prefix='') | ||||
|  | ||||
|     # @todo handle ctrl break | ||||
|     ticker_thread = threading.Thread(target=ticker_thread_check_time_launch_checks).start() | ||||
|   | ||||
| @@ -42,7 +42,7 @@ | ||||
|           <a class="pure-menu-heading" href="https://changedetection.io" rel="noopener"> | ||||
|             <strong>Change</strong>Detection.io</a> | ||||
|         {% else %} | ||||
|           <a class="pure-menu-heading" href="{{url_for('index')}}"> | ||||
|           <a class="pure-menu-heading" href="{{url_for('watchlist.index')}}"> | ||||
|             <strong>Change</strong>Detection.io</a> | ||||
|         {% endif %} | ||||
|         {% if current_diff_url %} | ||||
|   | ||||
| @@ -36,7 +36,7 @@ def test_select_custom(client, live_server, measure_memory_usage): | ||||
|     assert b"1 Imported" in res.data | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'Proxy Authentication Required' not in res.data | ||||
|  | ||||
|     res = client.get( | ||||
|   | ||||
| @@ -83,14 +83,14 @@ def test_restock_detection(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     # Is it correctly show as NOT in stock? | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'not-in-stock' in res.data | ||||
|  | ||||
|     # Is it correctly shown as in stock | ||||
|     set_back_in_stock_response() | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'not-in-stock' not in res.data | ||||
|  | ||||
|     # We should have a notification | ||||
| @@ -107,6 +107,6 @@ def test_restock_detection(client, live_server, measure_memory_usage): | ||||
|     assert not os.path.isfile("test-datastore/notification.txt"), "No notification should have fired when it went OUT OF STOCK by default" | ||||
|  | ||||
|     # BUT we should see that it correctly shows "not in stock" | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'not-in-stock' in res.data, "Correctly showing NOT IN STOCK in the list after it changed from IN STOCK" | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| from .util import live_server_setup | ||||
| from .util import live_server_setup, wait_for_all_checks | ||||
| from flask import url_for | ||||
| import time | ||||
|  | ||||
| @@ -44,7 +44,7 @@ def test_check_access_control(app, client, live_server): | ||||
|         assert b"Password protection enabled." in res.data | ||||
|  | ||||
|         # Check we hit the login | ||||
|         res = c.get(url_for("index"), follow_redirects=True) | ||||
|         res = c.get(url_for("watchlist.index"), follow_redirects=True) | ||||
|         # Should be logged out | ||||
|         assert b"Login" in res.data | ||||
|  | ||||
| @@ -52,6 +52,14 @@ def test_check_access_control(app, client, live_server): | ||||
|         res = c.get(url_for("ui.ui_views.diff_history_page", uuid="first")) | ||||
|         assert b'Random content' in res.data | ||||
|  | ||||
|         # access to assets should work (check_authentication) | ||||
|         res = c.get(url_for('static_content', group='js', filename='jquery-3.6.0.min.js')) | ||||
|         assert res.status_code == 200 | ||||
|         res = c.get(url_for('static_content', group='styles', filename='styles.css')) | ||||
|         assert res.status_code == 200 | ||||
|         res = c.get(url_for('static_content', group='styles', filename='404-testetest.css')) | ||||
|         assert res.status_code == 404 | ||||
|  | ||||
|         # Check wrong password does not let us in | ||||
|         res = c.post( | ||||
|             url_for("login"), | ||||
| @@ -164,7 +172,7 @@ def test_check_access_control(app, client, live_server): | ||||
|         assert b"Password protection enabled." in res.data | ||||
|  | ||||
|         # Check we hit the login | ||||
|         res = c.get(url_for("index"), follow_redirects=True) | ||||
|         res = c.get(url_for("watchlist.index"), follow_redirects=True) | ||||
|         # Should be logged out | ||||
|         assert b"Login" in res.data | ||||
|  | ||||
|   | ||||
| @@ -72,7 +72,7 @@ def test_check_removed_line_contains_trigger(client, live_server, measure_memory | ||||
|     res = client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     assert b'Queued 1 watch for rechecking.' in res.data | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     # The trigger line is REMOVED,  this should trigger | ||||
| @@ -81,7 +81,7 @@ def test_check_removed_line_contains_trigger(client, live_server, measure_memory | ||||
|     # Check in the processor here what's going on, its triggering empty-reply and no change. | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|  | ||||
| @@ -90,14 +90,14 @@ def test_check_removed_line_contains_trigger(client, live_server, measure_memory | ||||
|     set_original(excluding=None) | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     # Remove it again, and we should get a trigger | ||||
|     set_original(excluding='The golden line') | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
| @@ -157,14 +157,14 @@ def test_check_add_line_contains_trigger(client, live_server, measure_memory_usa | ||||
|     assert b'Queued 1 watch for rechecking.' in res.data | ||||
|  | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     # The trigger line is ADDED,  this should trigger | ||||
|     set_original(add_line='<p>Oh yes please</p>') | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|   | ||||
| @@ -383,7 +383,7 @@ def test_api_import(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     assert res.status_code == 200 | ||||
|     assert len(res.json) == 2 | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b"https://website1.com" in res.data | ||||
|     assert b"https://website2.com" in res.data | ||||
|  | ||||
|   | ||||
| @@ -95,7 +95,7 @@ def test_check_ldjson_price_autodetect(client, live_server, measure_memory_usage | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # Should get a notice that it's available | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'ldjson-price-track-offer' in res.data | ||||
|  | ||||
|     # Accept it | ||||
| @@ -105,7 +105,7 @@ def test_check_ldjson_price_autodetect(client, live_server, measure_memory_usage | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     # Offer should be gone | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'Embedded price data' not in res.data | ||||
|     assert b'tracking-ldjson-price-data' in res.data | ||||
|  | ||||
| @@ -136,7 +136,7 @@ def test_check_ldjson_price_autodetect(client, live_server, measure_memory_usage | ||||
|     ) | ||||
|     assert b"1 Imported" in res.data | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'ldjson-price-track-offer' not in res.data | ||||
|      | ||||
|     ########################################################################################## | ||||
|   | ||||
| @@ -39,7 +39,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|         wait_for_all_checks(client) | ||||
|  | ||||
|         # It should report nothing found (no new 'unviewed' class) | ||||
|         res = client.get(url_for("index")) | ||||
|         res = client.get(url_for("watchlist.index")) | ||||
|         assert b'unviewed' not in res.data | ||||
|         assert b'test-endpoint' in res.data | ||||
|  | ||||
| @@ -75,7 +75,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|     assert b'which has this one new line' in res.data | ||||
|  | ||||
|     # Now something should be ready, indicated by having a 'unviewed' class | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     # #75, and it should be in the RSS feed | ||||
| @@ -112,7 +112,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|         wait_for_all_checks(client) | ||||
|  | ||||
|         # It should report nothing found (no new 'unviewed' class) | ||||
|         res = client.get(url_for("index")) | ||||
|         res = client.get(url_for("watchlist.index")) | ||||
|         assert b'unviewed' not in res.data | ||||
|         assert b'Mark all viewed' not in res.data | ||||
|         assert b'head title' not in res.data  # Should not be present because this is off by default | ||||
| @@ -131,7 +131,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|     assert b'Mark all viewed' in res.data | ||||
|  | ||||
| @@ -151,7 +151,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|     client.get(url_for("ui.clear_watch_history", uuid=uuid)) | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'preview/' in res.data | ||||
|  | ||||
|     # | ||||
|   | ||||
| @@ -107,7 +107,7 @@ def test_check_block_changedetection_text_NOT_present(client, live_server, measu | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
|  | ||||
| @@ -120,7 +120,7 @@ def test_check_block_changedetection_text_NOT_present(client, live_server, measu | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
|  | ||||
| @@ -129,7 +129,7 @@ def test_check_block_changedetection_text_NOT_present(client, live_server, measu | ||||
|     set_original_ignore_response() | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|  | ||||
| @@ -137,7 +137,7 @@ def test_check_block_changedetection_text_NOT_present(client, live_server, measu | ||||
|     set_modified_response_minus_block_text() | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -114,7 +114,7 @@ def test_conditions_with_text_and_number(client, live_server): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # 75 is > 20 and < 100 and contains "5" | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|  | ||||
| @@ -128,7 +128,7 @@ def test_conditions_with_text_and_number(client, live_server): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # Should NOT be marked as having changes since not all conditions are met | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|   | ||||
| @@ -119,7 +119,7 @@ def test_check_markup_include_filters_restriction(client, live_server, measure_m | ||||
|  | ||||
|     # It should have 'unviewed' still | ||||
|     # Because it should be looking at only that 'sametext' id | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|  | ||||
| @@ -218,7 +218,7 @@ def test_filter_is_empty_help_suggestion(client, live_server, measure_memory_usa | ||||
|  | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("index"), | ||||
|         url_for("watchlist.index"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
| @@ -240,7 +240,7 @@ def test_filter_is_empty_help_suggestion(client, live_server, measure_memory_usa | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("index"), | ||||
|         url_for("watchlist.index"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|   | ||||
| @@ -204,7 +204,7 @@ def test_element_removal_full(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # There should not be an unviewed change, as changes should be removed | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b"unviewed" not in res.data | ||||
|  | ||||
| # Re #2752 | ||||
|   | ||||
| @@ -32,7 +32,7 @@ def _runner_test_http_errors(client, live_server, http_code, expected_text): | ||||
|     # Give the thread time to pick it up | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     # no change | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert bytes(expected_text.encode('utf-8')) in res.data | ||||
| @@ -78,7 +78,7 @@ def test_DNS_errors(client, live_server, measure_memory_usage): | ||||
|     # Give the thread time to pick it up | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     found_name_resolution_error = b"Temporary failure in name resolution" in res.data or b"Name or service not known" in res.data | ||||
|     assert found_name_resolution_error | ||||
|     # Should always record that we tried | ||||
| @@ -107,7 +107,7 @@ def test_low_level_errors_clear_correctly(client, live_server, measure_memory_us | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # We should see the DNS error | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     found_name_resolution_error = b"Temporary failure in name resolution" in res.data or b"Name or service not known" in res.data | ||||
|     assert found_name_resolution_error | ||||
|  | ||||
| @@ -122,7 +122,7 @@ def test_low_level_errors_clear_correctly(client, live_server, measure_memory_us | ||||
|  | ||||
|     # Now the error should be gone | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     found_name_resolution_error = b"Temporary failure in name resolution" in res.data or b"Name or service not known" in res.data | ||||
|     assert not found_name_resolution_error | ||||
|  | ||||
|   | ||||
| @@ -103,7 +103,7 @@ def test_check_filter_multiline(client, live_server, measure_memory_usage): | ||||
|     assert b"Updated watch." in res.data | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
|     # Issue 1828 | ||||
|     assert b'not at the start of the expression' not in res.data | ||||
| @@ -160,7 +160,7 @@ def test_check_filter_and_regex_extract(client, live_server, measure_memory_usag | ||||
|     # Give the thread time to pick it up | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     #issue 1828 | ||||
|     assert b'not at the start of the expression' not in res.data | ||||
|  | ||||
| @@ -174,7 +174,7 @@ def test_check_filter_and_regex_extract(client, live_server, measure_memory_usag | ||||
|  | ||||
|     # It should have 'unviewed' still | ||||
|     # Because it should be looking at only that 'sametext' id | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     # Check HTML conversion detected and workd | ||||
|   | ||||
| @@ -113,7 +113,7 @@ def run_filter_test(client, live_server, content_filter): | ||||
|         checked += 1 | ||||
|         client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|         wait_for_all_checks(client) | ||||
|         res = client.get(url_for("index")) | ||||
|         res = client.get(url_for("watchlist.index")) | ||||
|         assert b'Warning, no filters were found' in res.data | ||||
|         assert not os.path.isfile("test-datastore/notification.txt") | ||||
|         time.sleep(1) | ||||
|   | ||||
| @@ -77,7 +77,7 @@ def test_setup_group_tag(client, live_server, measure_memory_usage): | ||||
|     ) | ||||
|     assert b"1 Imported" in res.data | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'import-tag' in res.data | ||||
|     assert b'extra-import-tag' in res.data | ||||
|  | ||||
| @@ -90,7 +90,7 @@ def test_setup_group_tag(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'Warning, no filters were found' not in res.data | ||||
|  | ||||
|     res = client.get( | ||||
| @@ -255,7 +255,7 @@ def test_limit_tag_ui(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     assert b"40 Imported" in res.data | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'test-tag' in res.data | ||||
|  | ||||
|     # All should be here | ||||
| @@ -263,7 +263,7 @@ def test_limit_tag_ui(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     tag_uuid = get_UUID_for_tag_name(client, name="test-tag") | ||||
|  | ||||
|     res = client.get(url_for("index", tag=tag_uuid)) | ||||
|     res = client.get(url_for("watchlist.index", tag=tag_uuid)) | ||||
|  | ||||
|     # Just a subset should be here | ||||
|     assert b'test-tag' in res.data | ||||
| @@ -284,7 +284,7 @@ def test_clone_tag_on_import(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     assert b"1 Imported" in res.data | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'test-tag' in res.data | ||||
|     assert b'another-tag' in res.data | ||||
|  | ||||
| @@ -311,7 +311,7 @@ def test_clone_tag_on_quickwatchform_add(client, live_server, measure_memory_usa | ||||
|  | ||||
|     assert b"Watch added" in res.data | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'test-tag' in res.data | ||||
|     assert b'another-tag' in res.data | ||||
|  | ||||
|   | ||||
| @@ -127,7 +127,7 @@ def test_check_ignore_text_functionality(client, live_server, measure_memory_usa | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
|  | ||||
| @@ -140,7 +140,7 @@ def test_check_ignore_text_functionality(client, live_server, measure_memory_usa | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
|  | ||||
| @@ -151,7 +151,7 @@ def test_check_ignore_text_functionality(client, live_server, measure_memory_usa | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     res = client.get(url_for("ui.ui_views.preview_page", uuid="first")) | ||||
| @@ -214,7 +214,7 @@ def test_check_global_ignore_text_functionality(client, live_server, measure_mem | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     # It should report nothing found (no new 'unviewed' class), adding random ignore text should not cause a change | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
| ##### | ||||
| @@ -229,7 +229,7 @@ def test_check_global_ignore_text_functionality(client, live_server, measure_mem | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
| @@ -238,7 +238,7 @@ def test_check_global_ignore_text_functionality(client, live_server, measure_mem | ||||
|     set_modified_original_ignore_response() | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|   | ||||
| @@ -114,7 +114,7 @@ def test_render_anchor_tag_content_true(client, live_server, measure_memory_usag | ||||
|  | ||||
|     # since the link has changed, and we chose to render anchor tag content, | ||||
|     # we should detect a change (new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b"unviewed" in res.data | ||||
|     assert b"/test-endpoint" in res.data | ||||
|  | ||||
|   | ||||
| @@ -79,7 +79,7 @@ def test_normal_page_check_works_with_ignore_status_code(client, live_server, me | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
|  | ||||
| @@ -127,6 +127,6 @@ def test_403_page_check_works_with_ignore_status_code(client, live_server, measu | ||||
|  | ||||
|     # It should have 'unviewed' still | ||||
|     # Because it should be looking at only that 'sametext' id | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|   | ||||
| @@ -91,6 +91,6 @@ def test_check_ignore_whitespace(client, live_server, measure_memory_usage): | ||||
|     time.sleep(sleep_time_for_fetch_thread) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
|   | ||||
| @@ -31,8 +31,8 @@ https://example.com tag1, other tag""" | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|  | ||||
|     # Clear flask alerts | ||||
|     res = client.get( url_for("index")) | ||||
|     res = client.get( url_for("index")) | ||||
|     res = client.get( url_for("watchlist.index")) | ||||
|     res = client.get( url_for("watchlist.index")) | ||||
|  | ||||
| def xtest_import_skip_url(client, live_server, measure_memory_usage): | ||||
|  | ||||
| @@ -55,7 +55,7 @@ def xtest_import_skip_url(client, live_server, measure_memory_usage): | ||||
|     assert b"1 Skipped" in res.data | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|     # Clear flask alerts | ||||
|     res = client.get( url_for("index")) | ||||
|     res = client.get( url_for("watchlist.index")) | ||||
|  | ||||
| def test_import_distillio(client, live_server, measure_memory_usage): | ||||
|  | ||||
| @@ -113,7 +113,7 @@ def test_import_distillio(client, live_server, measure_memory_usage): | ||||
|     assert b"xpath:(//div[@id='App']/div[contains(@class,'flex')]/main[contains(@class,'relative')]/section[contains(@class,'relative')]/div[@class='container']/div[contains(@class,'flex')]/div[contains(@class,'w-full')])[1]" in res.data | ||||
|  | ||||
|     # did the tags work? | ||||
|     res = client.get( url_for("index")) | ||||
|     res = client.get( url_for("watchlist.index")) | ||||
|  | ||||
|     # check tags | ||||
|     assert b"nice stuff" in res.data | ||||
| @@ -121,7 +121,7 @@ def test_import_distillio(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|     # Clear flask alerts | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
| def test_import_custom_xlsx(client, live_server, measure_memory_usage): | ||||
|     """Test can upload a excel spreadsheet and the watches are created correctly""" | ||||
| @@ -156,7 +156,7 @@ def test_import_custom_xlsx(client, live_server, measure_memory_usage): | ||||
|     assert b'Error processing row number 1' in res.data | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("index") | ||||
|         url_for("watchlist.index") | ||||
|     ) | ||||
|  | ||||
|     assert b'Somesite results ABC' in res.data | ||||
| @@ -194,7 +194,7 @@ def test_import_watchete_xlsx(client, live_server, measure_memory_usage): | ||||
|     assert b'4 imported from Wachete .xlsx' in res.data | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("index") | ||||
|         url_for("watchlist.index") | ||||
|     ) | ||||
|  | ||||
|     assert b'Somesite results ABC' in res.data | ||||
|   | ||||
| @@ -52,7 +52,7 @@ def test_jinja2_security_url_query(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'is invalid and cannot be used' in res.data | ||||
|     # Some of the spewed output from the subclasses | ||||
|     assert b'dict_values' not in res.data | ||||
|   | ||||
| @@ -281,7 +281,7 @@ def check_json_filter(json_filter, client, live_server): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should have 'unviewed' still | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     # Should not see this, because its not in the JSONPath we entered | ||||
| @@ -417,7 +417,7 @@ def check_json_ext_filter(json_filter, client, live_server): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should have 'unviewed' | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     res = client.get(url_for("ui.ui_views.diff_history_page", uuid="first")) | ||||
| @@ -455,7 +455,7 @@ def test_ignore_json_order(client, live_server, measure_memory_usage): | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     # Just to be sure it still works | ||||
| @@ -466,7 +466,7 @@ def test_ignore_json_order(client, live_server, measure_memory_usage): | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
| @@ -488,7 +488,7 @@ def test_correct_header_detect(client, live_server, measure_memory_usage): | ||||
|     ) | ||||
|     assert b"1 Imported" in res.data | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
|     # Fixed in #1593 | ||||
|     assert b'No parsable JSON found in this document' not in res.data | ||||
|   | ||||
| @@ -41,7 +41,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|  | ||||
| @@ -63,7 +63,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     uuid = next(iter(live_server.app.config['DATASTORE'].data['watching'])) | ||||
| @@ -93,7 +93,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|     client.get(url_for("ui.mark_all_viewed"), follow_redirects=True) | ||||
|  | ||||
| @@ -105,7 +105,7 @@ def test_check_basic_change_detection_functionality(client, live_server, measure | ||||
|     assert watch.last_changed == watch['last_checked'] | ||||
|  | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data # A change should have registered because empty_pages_are_a_change is ON | ||||
|     assert b'fetch-error' not in res.data | ||||
|  | ||||
|   | ||||
| @@ -139,7 +139,7 @@ def test_check_notification(client, live_server, measure_memory_usage): | ||||
|     time.sleep(3) | ||||
|  | ||||
|     # Check no errors were recorded | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'notification-error' not in res.data | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -46,7 +46,7 @@ def test_check_notification_error_handling(client, live_server, measure_memory_u | ||||
|  | ||||
|         logging.debug("Fetching watch overview....") | ||||
|         res = client.get( | ||||
|             url_for("index")) | ||||
|             url_for("watchlist.index")) | ||||
|  | ||||
|         if bytes("Notification error detected".encode('utf-8')) in res.data: | ||||
|             found=True | ||||
|   | ||||
| @@ -50,7 +50,7 @@ def test_fetch_pdf(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # Now something should be ready, indicated by having a 'unviewed' class | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     # The original checksum should be not be here anymore (cdio adds it to the bottom of the text) | ||||
|   | ||||
| @@ -48,7 +48,7 @@ def test_fetch_pdf(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # Now something should be ready, indicated by having a 'unviewed' class | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     # The original checksum should be not be here anymore (cdio adds it to the bottom of the text) | ||||
|   | ||||
| @@ -64,7 +64,7 @@ def test_restock_itemprop_basic(client, live_server): | ||||
|             follow_redirects=True | ||||
|         ) | ||||
|         wait_for_all_checks(client) | ||||
|         res = client.get(url_for("index")) | ||||
|         res = client.get(url_for("watchlist.index")) | ||||
|         assert b'more than one price detected' not in res.data | ||||
|         assert b'has-restock-info' in res.data | ||||
|         assert b' in-stock' in res.data | ||||
| @@ -81,7 +81,7 @@ def test_restock_itemprop_basic(client, live_server): | ||||
|             follow_redirects=True | ||||
|         ) | ||||
|         wait_for_all_checks(client) | ||||
|         res = client.get(url_for("index")) | ||||
|         res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
|         assert b'has-restock-info not-in-stock' in res.data | ||||
|  | ||||
| @@ -103,14 +103,14 @@ def test_itemprop_price_change(client, live_server): | ||||
|  | ||||
|     # A change in price, should trigger a change by default | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'190.95' in res.data | ||||
|  | ||||
|     # basic price change, look for notification | ||||
|     set_original_response(props_markup=instock_props[0], price='180.45') | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'180.45' in res.data | ||||
|     assert b'unviewed' in res.data | ||||
|     client.get(url_for("ui.mark_all_viewed"), follow_redirects=True) | ||||
| @@ -125,7 +125,7 @@ def test_itemprop_price_change(client, live_server): | ||||
|     assert b"Updated watch." in res.data | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'120.45' in res.data | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
| @@ -170,7 +170,7 @@ def _run_test_minmax_limit(client, extra_watch_edit_form): | ||||
|     set_original_response(props_markup=instock_props[0], price='1000.45') | ||||
|     client.get(url_for("ui.form_watch_checknow")) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
|     assert b'more than one price detected' not in res.data | ||||
|     # BUT the new price should show, even tho its within limits | ||||
| @@ -183,7 +183,7 @@ def _run_test_minmax_limit(client, extra_watch_edit_form): | ||||
|     res = client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     assert b'Queued 1 watch for rechecking.' in res.data | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'890.45' in res.data | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
| @@ -195,7 +195,7 @@ def _run_test_minmax_limit(client, extra_watch_edit_form): | ||||
|     res = client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     assert b'Queued 1 watch for rechecking.' in res.data | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'820.45' in res.data | ||||
|     assert b'unviewed' in res.data | ||||
|     client.get(url_for("ui.mark_all_viewed")) | ||||
| @@ -204,7 +204,7 @@ def _run_test_minmax_limit(client, extra_watch_edit_form): | ||||
|     set_original_response(props_markup=instock_props[0], price='1890.45') | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     # Depending on the LOCALE it may be either of these (generally for US/default/etc) | ||||
|     assert b'1,890.45' in res.data or b'1890.45' in res.data | ||||
|     assert b'unviewed' in res.data | ||||
| @@ -288,7 +288,7 @@ def test_itemprop_percent_threshold(client, live_server): | ||||
|     set_original_response(props_markup=instock_props[0], price='960.45') | ||||
|     client.get(url_for("ui.form_watch_checknow")) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'960.45' in res.data | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
| @@ -296,7 +296,7 @@ def test_itemprop_percent_threshold(client, live_server): | ||||
|     set_original_response(props_markup=instock_props[0], price='1960.45') | ||||
|     client.get(url_for("ui.form_watch_checknow")) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'1,960.45' or b'1960.45' in res.data #depending on locale | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
| @@ -306,7 +306,7 @@ def test_itemprop_percent_threshold(client, live_server): | ||||
|     set_original_response(props_markup=instock_props[0], price='1950.45') | ||||
|     client.get(url_for("ui.form_watch_checknow")) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'1,950.45' or b'1950.45' in res.data #depending on locale | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
| @@ -403,7 +403,7 @@ def test_data_sanity(client, live_server): | ||||
|  | ||||
|  | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'950.95' in res.data | ||||
|  | ||||
|     # Check the restock model object doesnt store the value by mistake and used in a new one | ||||
| @@ -413,7 +413,7 @@ def test_data_sanity(client, live_server): | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert str(res.data.decode()).count("950.95") == 1, "Price should only show once (for the watch added, no other watches yet)" | ||||
|  | ||||
|     ## different test, check the edit page works on an empty request result | ||||
| @@ -455,6 +455,6 @@ def test_special_prop_examples(client, live_server): | ||||
|                 follow_redirects=True | ||||
|             ) | ||||
|             wait_for_all_checks(client) | ||||
|             res = client.get(url_for("index")) | ||||
|             res = client.get(url_for("watchlist.index")) | ||||
|             assert b'ception' not in res.data | ||||
|             assert b'155.55' in res.data | ||||
|   | ||||
| @@ -20,7 +20,7 @@ def test_basic_search(client, live_server, measure_memory_usage): | ||||
|     assert b"2 Imported" in res.data | ||||
|  | ||||
|     # By URL | ||||
|     res = client.get(url_for("index") + "?q=first-res") | ||||
|     res = client.get(url_for("watchlist.index") + "?q=first-res") | ||||
|     assert urls[0].encode('utf-8') in res.data | ||||
|     assert urls[1].encode('utf-8') not in res.data | ||||
|  | ||||
| @@ -33,7 +33,7 @@ def test_basic_search(client, live_server, measure_memory_usage): | ||||
|     ) | ||||
|     assert b"Updated watch." in res.data | ||||
|  | ||||
|     res = client.get(url_for("index") + "?q=xxx-title") | ||||
|     res = client.get(url_for("watchlist.index") + "?q=xxx-title") | ||||
|     assert urls[0].encode('utf-8') in res.data | ||||
|     assert urls[1].encode('utf-8') not in res.data | ||||
|  | ||||
| @@ -54,7 +54,7 @@ def test_search_in_tag_limit(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     # By URL | ||||
|  | ||||
|     res = client.get(url_for("index") + "?q=first-res") | ||||
|     res = client.get(url_for("watchlist.index") + "?q=first-res") | ||||
|     # Split because of the import tag separation | ||||
|     assert urls[0].split(' ')[0].encode('utf-8') in res.data, urls[0].encode('utf-8') | ||||
|     assert urls[1].split(' ')[0].encode('utf-8') not in res.data, urls[0].encode('utf-8') | ||||
| @@ -68,7 +68,7 @@ def test_search_in_tag_limit(client, live_server, measure_memory_usage): | ||||
|     ) | ||||
|     assert b"Updated watch." in res.data | ||||
|  | ||||
|     res = client.get(url_for("index") + "?q=xxx-title") | ||||
|     res = client.get(url_for("watchlist.index") + "?q=xxx-title") | ||||
|     assert urls[0].split(' ')[0].encode('utf-8') in res.data, urls[0].encode('utf-8') | ||||
|     assert urls[1].split(' ')[0].encode('utf-8') not in res.data, urls[0].encode('utf-8') | ||||
|  | ||||
|   | ||||
| @@ -67,7 +67,7 @@ def _runner_test_various_file_slash(client, file_uri): | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|  | ||||
|     substrings = [b"URLs with hostname components are not permitted", b"No connection adapters were found for"] | ||||
|  | ||||
|   | ||||
| @@ -76,5 +76,5 @@ def test_share_watch(client, live_server, measure_memory_usage): | ||||
|     assert bytes(include_filters.encode('utf-8')) in res.data | ||||
|  | ||||
|     # Check it saved the URL | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert bytes(test_url.encode('utf-8')) in res.data | ||||
|   | ||||
| @@ -45,7 +45,7 @@ def test_check_basic_change_detection_functionality_source(client, live_server, | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # Now something should be ready, indicated by having a 'unviewed' class | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     res = client.get( | ||||
|   | ||||
| @@ -104,7 +104,7 @@ def test_trigger_functionality(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     assert b'/test-endpoint' in res.data | ||||
|  | ||||
| @@ -116,7 +116,7 @@ def test_trigger_functionality(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     # Now set the content which contains the trigger text | ||||
| @@ -124,7 +124,7 @@ def test_trigger_functionality(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|      | ||||
|     # https://github.com/dgtlmoon/changedetection.io/issues/616 | ||||
|   | ||||
| @@ -41,7 +41,7 @@ def test_trigger_regex_functionality(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (just a new one shouldnt have anything) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     ### test regex | ||||
| @@ -63,7 +63,7 @@ def test_trigger_regex_functionality(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (nothing should match the regex) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     with open("test-datastore/endpoint-content.txt", "w") as f: | ||||
| @@ -71,7 +71,7 @@ def test_trigger_regex_functionality(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|     # Cleanup everything | ||||
|   | ||||
| @@ -67,7 +67,7 @@ def test_trigger_regex_functionality_with_filter(client, live_server, measure_me | ||||
|     time.sleep(sleep_time_for_fetch_thread) | ||||
|  | ||||
|     # It should report nothing found (nothing should match the regex and filter) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     # now this should trigger something | ||||
| @@ -76,7 +76,7 @@ def test_trigger_regex_functionality_with_filter(client, live_server, measure_me | ||||
|  | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     time.sleep(sleep_time_for_fetch_thread) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
| # Cleanup everything | ||||
|   | ||||
| @@ -108,14 +108,14 @@ def test_unique_lines_functionality(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     # It should report nothing found (no new 'unviewed' class) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|  | ||||
|     # Now set the content which contains the new text and re-ordered existing text | ||||
|     set_modified_with_trigger_text_response() | ||||
|     client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' in res.data | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|     assert b'Deleted' in res.data | ||||
| @@ -153,7 +153,7 @@ def test_sort_lines_functionality(client, live_server, measure_memory_usage): | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     # Should be a change registered | ||||
|     assert b'unviewed' in res.data | ||||
|  | ||||
|   | ||||
| @@ -98,7 +98,7 @@ def test_check_xpath_filter_utf8(client, live_server, measure_memory_usage): | ||||
|     ) | ||||
|     assert b"Updated watch." in res.data | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'Unicode strings with encoding declaration are not supported.' not in res.data | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|     assert b'Deleted' in res.data | ||||
| @@ -152,7 +152,7 @@ def test_check_xpath_text_function_utf8(client, live_server, measure_memory_usag | ||||
|     ) | ||||
|     assert b"Updated watch." in res.data | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'Unicode strings with encoding declaration are not supported.' not in res.data | ||||
|  | ||||
|     # The service should echo back the request headers | ||||
| @@ -208,7 +208,7 @@ def test_check_markup_xpath_filter_restriction(client, live_server, measure_memo | ||||
|     # Give the thread time to pick it up | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'unviewed' not in res.data | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|     assert b'Deleted' in res.data | ||||
| @@ -305,7 +305,7 @@ def test_xpath1_lxml(client, live_server, measure_memory_usage): | ||||
|  | ||||
|     ##### #2312 | ||||
|     wait_for_all_checks(client) | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     assert b'_ElementStringResult' not in res.data # tested with 5.1.1 when it was removed and 5.1.0 | ||||
|     assert b'Exception' not in res.data | ||||
|     res = client.get( | ||||
| @@ -419,7 +419,7 @@ def test_various_rules(client, live_server, measure_memory_usage): | ||||
|         ) | ||||
|         wait_for_all_checks(client) | ||||
|         assert b"Updated watch." in res.data | ||||
|         res = client.get(url_for("index")) | ||||
|         res = client.get(url_for("watchlist.index")) | ||||
|         assert b'fetch-error' not in res.data, f"Should not see errors after '{r} filter" | ||||
|  | ||||
|     res = client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) | ||||
|   | ||||
| @@ -108,7 +108,7 @@ def get_UUID_for_tag_name(client, name): | ||||
| def extract_rss_token_from_UI(client): | ||||
|     import re | ||||
|     res = client.get( | ||||
|         url_for("index"), | ||||
|         url_for("watchlist.index"), | ||||
|     ) | ||||
|     m = re.search('token=(.+?)"', str(res.data)) | ||||
|     token_key = m.group(1) | ||||
| @@ -118,7 +118,7 @@ def extract_rss_token_from_UI(client): | ||||
| def extract_UUID_from_client(client): | ||||
|     import re | ||||
|     res = client.get( | ||||
|         url_for("index"), | ||||
|         url_for("watchlist.index"), | ||||
|     ) | ||||
|     # <span id="api-key">{{api_key}}</span> | ||||
|  | ||||
| @@ -133,7 +133,7 @@ def wait_for_all_checks(client): | ||||
|     # because sub-second rechecks are problematic in testing, use lots of delays | ||||
|     time.sleep(1) | ||||
|     while attempt < 60: | ||||
|         res = client.get(url_for("index")) | ||||
|         res = client.get(url_for("watchlist.index")) | ||||
|         if not b'Checking now' in res.data: | ||||
|             break | ||||
|         logging.getLogger().info("Waiting for watch-list to not say 'Checking now'.. {}".format(attempt)) | ||||
| @@ -306,7 +306,7 @@ def get_index(client): | ||||
|  | ||||
|     print(f"Called by: {caller_name}, Line: {caller_line}") | ||||
|  | ||||
|     res = client.get(url_for("index")) | ||||
|     res = client.get(url_for("watchlist.index")) | ||||
|     with open(f"test-datastore/index-{caller_name}-{caller_line}.html", 'wb') as f: | ||||
|         f.write(res.data) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user